Skip to content

Commit 1a9bcba

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 5146532 commit 1a9bcba

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

@@ -307,6 +322,8 @@ void tone_expiry_cb(struct k_timer *timer) {
307322
}
308323

309324
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
325+
RETURN_ON_INVALID_PIN(pinNumber);
326+
310327
k_spinlock_key_t key;
311328
struct pin_timer *pt;
312329
k_timeout_t timeout;
@@ -347,6 +364,8 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
347364
}
348365

349366
void noTone(pin_size_t pinNumber) {
367+
RETURN_ON_INVALID_PIN(pinNumber);
368+
350369
struct pin_timer *pt;
351370
k_spinlock_key_t key;
352371

@@ -527,6 +546,8 @@ int analogRead(pin_size_t pinNumber) {
527546
#endif
528547

529548
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) {
549+
RETURN_ON_INVALID_PIN(pinNumber);
550+
530551
struct gpio_port_callback *pcb;
531552
gpio_flags_t intmode = 0;
532553

@@ -562,6 +583,8 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
562583
}
563584

564585
void detachInterrupt(pin_size_t pinNumber) {
586+
RETURN_ON_INVALID_PIN(pinNumber);
587+
565588
setInterruptHandler(pinNumber, nullptr);
566589
disableInterrupt(pinNumber);
567590
}
@@ -585,6 +608,8 @@ long random(long max) {
585608
#endif
586609

587610
unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) {
611+
RETURN_ON_INVALID_PIN(pinNumber, LOW);
612+
588613
struct k_timer timer;
589614
int64_t start, end, delta = 0;
590615
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
@@ -624,6 +649,8 @@ unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout
624649
}
625650

626651
void enableInterrupt(pin_size_t pinNumber) {
652+
RETURN_ON_INVALID_PIN(pinNumber);
653+
627654
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
628655

629656
if (pcb) {
@@ -632,6 +659,8 @@ void enableInterrupt(pin_size_t pinNumber) {
632659
}
633660

634661
void disableInterrupt(pin_size_t pinNumber) {
662+
RETURN_ON_INVALID_PIN(pinNumber);
663+
635664
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
636665

637666
if (pcb) {
@@ -653,8 +682,10 @@ void noInterrupts(void) {
653682
}
654683
}
655684

656-
int digitalPinToInterrupt(pin_size_t pin) {
657-
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port);
685+
int digitalPinToInterrupt(pin_size_t pinNumber) {
686+
RETURN_ON_INVALID_PIN(pinNumber, -1);
687+
688+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
658689

659-
return (pcb) ? pin : -1;
690+
return (pcb) ? pinNumber : -1;
660691
}

0 commit comments

Comments
 (0)