@@ -169,24 +169,51 @@ extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
169169// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
170170extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM [];
171171extern const uint8_t PROGMEM digital_pin_to_timer_PGM [];
172+ extern const uint8_t digital_pin_count ;
173+
174+ #define NOT_A_PIN 0
175+ #define NOT_A_PORT 0
176+
177+ #define NOT_AN_INTERRUPT -1
172178
173179// Get the bit location within the hardware port of the given virtual pin.
174180// This comes from the pins_*.c file for the active board configuration.
175181//
176182// These perform slightly better as macros compared to inline functions
177- //
178- #define digitalPinToPort (P ) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
179- #define digitalPinToBitMask (P ) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
180- #define digitalPinToTimer (P ) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
183+ //
181184#define analogInPinToBit (P ) (P)
182185#define portOutputRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
183186#define portInputRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
184187#define portModeRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
185-
186- #define NOT_A_PIN 0
187- #define NOT_A_PORT 0
188-
189- #define NOT_AN_INTERRUPT -1
188+ //
189+ // bounds checking on these functions because they return a pointer to an address that will be modified.
190+ // An out of bounds write can result in stack corruption and fun to track-down errors.
191+ //
192+ static inline const uint8_t digitalPinToPort (const uint8_t P ) {
193+ if (P > digital_pin_count ) {
194+ return NOT_A_PIN ;
195+ } else {
196+ return pgm_read_byte ( digital_pin_to_port_PGM + P );
197+ }
198+ }
199+ static inline const uint8_t digitalPinToBitMask (const uint8_t P ) {
200+ if (P > digital_pin_count ) {
201+ return NOT_A_PIN ;
202+ } else {
203+ return pgm_read_byte ( digital_pin_to_bit_mask_PGM + P );
204+ }
205+ }
206+ static inline const uint8_t digitalPinToTimer (const uint8_t P ) {
207+ if (P > digital_pin_count ) {
208+ return NOT_A_PIN ;
209+ } else {
210+ return pgm_read_byte ( digital_pin_to_timer_PGM + P );
211+ }
212+ }
213+ // these defines are to maintain backwards compatibility with #ifdef
214+ #define digitalPinToPort digitalPinToPort
215+ #define digitalPinToBitMask digitalPinToBitMask
216+ #define digitalPinToTimer digitalPinToTimer
190217
191218#ifdef ARDUINO_MAIN
192219#define PA 1
0 commit comments