-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added bounds checking on pinMode #302
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,24 +169,51 @@ extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; | |
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; | ||
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; | ||
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; | ||
extern const uint8_t digital_pin_count; | ||
|
||
#define NOT_A_PIN 0 | ||
#define NOT_A_PORT 0 | ||
|
||
#define NOT_AN_INTERRUPT -1 | ||
|
||
// Get the bit location within the hardware port of the given virtual pin. | ||
// This comes from the pins_*.c file for the active board configuration. | ||
// | ||
// These perform slightly better as macros compared to inline functions | ||
// | ||
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) | ||
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) | ||
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) | ||
// | ||
#define analogInPinToBit(P) (P) | ||
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) | ||
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) | ||
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) | ||
|
||
#define NOT_A_PIN 0 | ||
#define NOT_A_PORT 0 | ||
|
||
#define NOT_AN_INTERRUPT -1 | ||
// | ||
// bounds checking on these functions because they return a pointer to an address that will be modified. | ||
// An out of bounds write can result in stack corruption and fun to track-down errors. | ||
// | ||
static inline uint8_t digitalPinToPort(const uint8_t P) { | ||
if (P >= digital_pin_count) { | ||
return NOT_A_PIN; | ||
} else { | ||
return pgm_read_byte( digital_pin_to_port_PGM + P ); | ||
} | ||
} | ||
static inline uint8_t digitalPinToBitMask(const uint8_t P) { | ||
if (P >= digital_pin_count) { | ||
return NOT_A_PIN; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly here, it is not clear whether There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you reviewing the latest commit? That should be a It's following the same convention already in place in Do you think that it is not obvious from the code what the situation is, that a comment is needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was: the semantics of the The (The term "PORT" seems to be overloaded in The Similarly, the These 3 functions are returning 3 conceptually separate things, and I got confused why all of them are returning a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please familiarise yourself with how these functions are currently used and implemented.They have no documentation of their API, so their existing use defines the API. wiring_digital.c and the various pins_arduino.h are good places to look. You will see that the new implementations are consistent with the existing API, as I explained above. You are requesting that the existing API change. That is out of scope of this pull request. Please create a separate pull request or issue. I do not feel that a comment explaining that a function conforms to the rest of the (undocumented, uncommented) API is necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's even more important to add comments to describe your assumptions when you are making changes on top of undocumented and uncommented API. I have reviewed the usage of As far as I can tell, If you choose to ignore my feedback and continue to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For
For
For
So, for The same logic applies to Unfortunately it appears that the writer of So:
Both of those options are out of scope for this PR and more than I'm prepared to do. As I say, please deal with the issue in a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the intended limited scope of this PR. But your changes to The problem that you found in The return type of The return type of Finally, the return type of case NOT_ON_TIMER:
default:
if (val < 128) {
digitalWrite(pin, LOW);
} else {
digitalWrite(pin, HIGH);
} If At this point, the simplest fix I can see that will implement the intended scope of this PR is to remove the checks for static inline uint8_t digitalPinToBitMask(const uint8_t P) {
return pgm_read_byte( digital_pin_to_bit_mask_PGM + P );
}
static inline uint8_t digitalPinToTimer(const uint8_t P) {
return pgm_read_byte( digital_pin_to_timer_PGM + P );
} I cannot see how returning the |
||
} else { | ||
return pgm_read_byte( digital_pin_to_bit_mask_PGM + P ); | ||
} | ||
} | ||
static inline uint8_t digitalPinToTimer(const uint8_t P) { | ||
if (P >= digital_pin_count) { | ||
return NOT_A_PIN; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you reviewing the latest commit? That should be a It's following the same convention already in place in Do you think that it is not obvious from the code what the situation is, that a comment is needed? |
||
} else { | ||
return pgm_read_byte( digital_pin_to_timer_PGM + P ); | ||
} | ||
} | ||
// these defines are to maintain backwards compatibility with #ifdef | ||
#define digitalPinToPort digitalPinToPort | ||
#define digitalPinToBitMask digitalPinToBitMask | ||
#define digitalPinToTimer digitalPinToTimer | ||
|
||
#ifdef ARDUINO_MAIN | ||
#define PA 1 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me whether NOT_A_PIN is an invalid port number, or whether it is a valid port number that is returned for an invalid pin. Can you add a comment to make that more clear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you reviewing the latest commit? That should be a
>=
.It's following the same convention already in place in
pinMode
, where the returned value ofdigitalPinToPort
is compared againstNOT_A_PIN
to see if the input was a pin.Do you think that it is not obvious from the code what the situation is, that a comment is needed?