From e6531a00282a0f87c80b2d04cf7e71ca6c4b6207 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 13 Mar 2026 14:36:25 +0100 Subject: [PATCH] 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 Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 37 +++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index e83854fec..9e8300a9f 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -13,6 +13,13 @@ static const struct gpio_dt_spec arduino_pins[] = { DT_FOREACH_PROP_ELEM_SEP( DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; +#define RETURN_ON_INVALID_PIN(pinNumber, ...) \ + do { \ + if ((pin_size_t)(pinNumber) >= ARRAY_SIZE(arduino_pins)) { \ + return __VA_ARGS__; \ + } \ + } while (0) + namespace { #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) { } void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) { + RETURN_ON_INVALID_PIN(pinNumber); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); if (pcb) { @@ -215,6 +224,8 @@ void yield(void) { * A high physical level will be interpreted as value 1 */ void pinMode(pin_size_t pinNumber, PinMode pinMode) { + RETURN_ON_INVALID_PIN(pinNumber); + if (pinMode == INPUT) { // input mode gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT | GPIO_ACTIVE_HIGH); } else if (pinMode == INPUT_PULLUP) { // input with internal pull-up @@ -229,10 +240,14 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) { } void digitalWrite(pin_size_t pinNumber, PinStatus status) { + RETURN_ON_INVALID_PIN(pinNumber); + gpio_pin_set_dt(&arduino_pins[pinNumber], status); } PinStatus digitalRead(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber, LOW); + return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW; } @@ -314,6 +329,8 @@ void tone_expiry_cb(struct k_timer *timer) { } void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) { + RETURN_ON_INVALID_PIN(pinNumber); + k_spinlock_key_t key; uint64_t toggles_count; struct pin_timer *pt; @@ -372,6 +389,8 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) } void noTone(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber); + struct pin_timer *pt; k_spinlock_key_t key; @@ -563,6 +582,8 @@ int analogRead(pin_size_t pinNumber) { #endif void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) { + RETURN_ON_INVALID_PIN(pinNumber); + struct gpio_port_callback *pcb; gpio_flags_t intmode = 0; @@ -598,6 +619,8 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt } void detachInterrupt(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber); + setInterruptHandler(pinNumber, nullptr); disableInterrupt(pinNumber); } @@ -621,6 +644,8 @@ long random(long max) { #endif unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) { + RETURN_ON_INVALID_PIN(pinNumber, LOW); + struct k_timer timer; int64_t start, end, delta = 0; 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 } void enableInterrupt(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); if (pcb) { @@ -668,6 +695,8 @@ void enableInterrupt(pin_size_t pinNumber) { } void disableInterrupt(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); if (pcb) { @@ -689,8 +718,10 @@ void noInterrupts(void) { } } -int digitalPinToInterrupt(pin_size_t pin) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port); +int digitalPinToInterrupt(pin_size_t pinNumber) { + RETURN_ON_INVALID_PIN(pinNumber, -1); + + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); - return (pcb) ? pin : -1; + return (pcb) ? pinNumber : -1; }