Skip to content

Commit a7ff7cb

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 00f4456 commit a7ff7cb

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
@@ -26,6 +26,13 @@ static const struct gpio_dt_spec arduino_pins[] = {
2626
DT_FOREACH_PROP_ELEM_SEP(
2727
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
2828

29+
#define RETURN_ON_INVALID_PIN(pinNumber, ...) \
30+
do { \
31+
if ((pin_size_t)(pinNumber) >= ARRAY_SIZE(arduino_pins)) { \
32+
return __VA_ARGS__; \
33+
} \
34+
} while (0)
35+
2936
namespace {
3037

3138
#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0
@@ -116,6 +123,8 @@ struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) {
116123
}
117124

118125
void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) {
126+
RETURN_ON_INVALID_PIN(pinNumber);
127+
119128
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
120129

121130
if (pcb) {
@@ -228,6 +237,8 @@ void yield(void) {
228237
* A high physical level will be interpreted as value 1
229238
*/
230239
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
240+
RETURN_ON_INVALID_PIN(pinNumber);
241+
231242
_reinit_peripheral_if_needed(pinNumber, NULL);
232243
if (pinMode == INPUT) { // input mode
233244
gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT | GPIO_ACTIVE_HIGH);
@@ -243,10 +254,14 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) {
243254
}
244255

245256
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
257+
RETURN_ON_INVALID_PIN(pinNumber);
258+
246259
gpio_pin_set_dt(&arduino_pins[pinNumber], status);
247260
}
248261

249262
PinStatus digitalRead(pin_size_t pinNumber) {
263+
RETURN_ON_INVALID_PIN(pinNumber, LOW);
264+
250265
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
251266
}
252267

@@ -328,6 +343,8 @@ void tone_expiry_cb(struct k_timer *timer) {
328343
}
329344

330345
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
346+
RETURN_ON_INVALID_PIN(pinNumber);
347+
331348
k_spinlock_key_t key;
332349
uint64_t toggles_count;
333350
struct pin_timer *pt;
@@ -386,6 +403,8 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
386403
}
387404

388405
void noTone(pin_size_t pinNumber) {
406+
RETURN_ON_INVALID_PIN(pinNumber);
407+
389408
struct pin_timer *pt;
390409
k_spinlock_key_t key;
391410

@@ -583,6 +602,8 @@ int analogRead(pin_size_t pinNumber) {
583602
#endif
584603

585604
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) {
605+
RETURN_ON_INVALID_PIN(pinNumber);
606+
586607
struct gpio_port_callback *pcb;
587608
gpio_flags_t intmode = 0;
588609

@@ -618,6 +639,8 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
618639
}
619640

620641
void detachInterrupt(pin_size_t pinNumber) {
642+
RETURN_ON_INVALID_PIN(pinNumber);
643+
621644
setInterruptHandler(pinNumber, nullptr);
622645
disableInterrupt(pinNumber);
623646
}
@@ -641,6 +664,8 @@ long random(long max) {
641664
#endif
642665

643666
unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) {
667+
RETURN_ON_INVALID_PIN(pinNumber, LOW);
668+
644669
struct k_timer timer;
645670
int64_t start, end, delta = 0;
646671
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
@@ -680,6 +705,8 @@ unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout
680705
}
681706

682707
void enableInterrupt(pin_size_t pinNumber) {
708+
RETURN_ON_INVALID_PIN(pinNumber);
709+
683710
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
684711

685712
if (pcb) {
@@ -688,6 +715,8 @@ void enableInterrupt(pin_size_t pinNumber) {
688715
}
689716

690717
void disableInterrupt(pin_size_t pinNumber) {
718+
RETURN_ON_INVALID_PIN(pinNumber);
719+
691720
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
692721

693722
if (pcb) {
@@ -709,8 +738,10 @@ void noInterrupts(void) {
709738
}
710739
}
711740

712-
int digitalPinToInterrupt(pin_size_t pin) {
713-
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port);
741+
int digitalPinToInterrupt(pin_size_t pinNumber) {
742+
RETURN_ON_INVALID_PIN(pinNumber, -1);
743+
744+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
714745

715-
return (pcb) ? pin : -1;
746+
return (pcb) ? pinNumber : -1;
716747
}

0 commit comments

Comments
 (0)