Skip to content

Commit e6531a0

Browse files
pillo79soburi
authored andcommitted
zephyrCommon: fix issues with invalid pin numbers
Passing -1 to digital I/O functions may happen when libraries do not properly sanitize their inputs, leading to undefined behavior. This commit adds a check to ensure that the pin number is valid before accessing the arduino_pins array. Signed-off-by: Luca Burelli <l.burelli@arduino.cc> Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 1316b52 commit e6531a0

1 file changed

Lines changed: 34 additions & 3 deletions

File tree

cores/arduino/zephyrCommon.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ static const struct gpio_dt_spec arduino_pins[] = {
1313
DT_FOREACH_PROP_ELEM_SEP(
1414
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
1515

16+
#define RETURN_ON_INVALID_PIN(pinNumber, ...) \
17+
do { \
18+
if ((pin_size_t)(pinNumber) >= ARRAY_SIZE(arduino_pins)) { \
19+
return __VA_ARGS__; \
20+
} \
21+
} while (0)
22+
1623
namespace {
1724

1825
#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0
@@ -103,6 +110,8 @@ struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) {
103110
}
104111

105112
void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) {
113+
RETURN_ON_INVALID_PIN(pinNumber);
114+
106115
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
107116

108117
if (pcb) {
@@ -215,6 +224,8 @@ void yield(void) {
215224
* A high physical level will be interpreted as value 1
216225
*/
217226
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
227+
RETURN_ON_INVALID_PIN(pinNumber);
228+
218229
if (pinMode == INPUT) { // input mode
219230
gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT | GPIO_ACTIVE_HIGH);
220231
} else if (pinMode == INPUT_PULLUP) { // input with internal pull-up
@@ -229,10 +240,14 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) {
229240
}
230241

231242
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
243+
RETURN_ON_INVALID_PIN(pinNumber);
244+
232245
gpio_pin_set_dt(&arduino_pins[pinNumber], status);
233246
}
234247

235248
PinStatus digitalRead(pin_size_t pinNumber) {
249+
RETURN_ON_INVALID_PIN(pinNumber, LOW);
250+
236251
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
237252
}
238253

@@ -314,6 +329,8 @@ void tone_expiry_cb(struct k_timer *timer) {
314329
}
315330

316331
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
332+
RETURN_ON_INVALID_PIN(pinNumber);
333+
317334
k_spinlock_key_t key;
318335
uint64_t toggles_count;
319336
struct pin_timer *pt;
@@ -372,6 +389,8 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
372389
}
373390

374391
void noTone(pin_size_t pinNumber) {
392+
RETURN_ON_INVALID_PIN(pinNumber);
393+
375394
struct pin_timer *pt;
376395
k_spinlock_key_t key;
377396

@@ -563,6 +582,8 @@ int analogRead(pin_size_t pinNumber) {
563582
#endif
564583

565584
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) {
585+
RETURN_ON_INVALID_PIN(pinNumber);
586+
566587
struct gpio_port_callback *pcb;
567588
gpio_flags_t intmode = 0;
568589

@@ -598,6 +619,8 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
598619
}
599620

600621
void detachInterrupt(pin_size_t pinNumber) {
622+
RETURN_ON_INVALID_PIN(pinNumber);
623+
601624
setInterruptHandler(pinNumber, nullptr);
602625
disableInterrupt(pinNumber);
603626
}
@@ -621,6 +644,8 @@ long random(long max) {
621644
#endif
622645

623646
unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) {
647+
RETURN_ON_INVALID_PIN(pinNumber, LOW);
648+
624649
struct k_timer timer;
625650
int64_t start, end, delta = 0;
626651
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
@@ -660,6 +685,8 @@ unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout
660685
}
661686

662687
void enableInterrupt(pin_size_t pinNumber) {
688+
RETURN_ON_INVALID_PIN(pinNumber);
689+
663690
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
664691

665692
if (pcb) {
@@ -668,6 +695,8 @@ void enableInterrupt(pin_size_t pinNumber) {
668695
}
669696

670697
void disableInterrupt(pin_size_t pinNumber) {
698+
RETURN_ON_INVALID_PIN(pinNumber);
699+
671700
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
672701

673702
if (pcb) {
@@ -689,8 +718,10 @@ void noInterrupts(void) {
689718
}
690719
}
691720

692-
int digitalPinToInterrupt(pin_size_t pin) {
693-
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port);
721+
int digitalPinToInterrupt(pin_size_t pinNumber) {
722+
RETURN_ON_INVALID_PIN(pinNumber, -1);
723+
724+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
694725

695-
return (pcb) ? pin : -1;
726+
return (pcb) ? pinNumber : -1;
696727
}

0 commit comments

Comments
 (0)