Skip to content

drivers: gpio: esp32: fix BIT overflow for pins >= 32#107124

Merged
nashif merged 2 commits intozephyrproject-rtos:mainfrom
matinlotfali:fix/gpio-esp32-bit64-overflow
Apr 15, 2026
Merged

drivers: gpio: esp32: fix BIT overflow for pins >= 32#107124
nashif merged 2 commits intozephyrproject-rtos:mainfrom
matinlotfali:fix/gpio-esp32-bit64-overflow

Conversation

@matinlotfali
Copy link
Copy Markdown
Contributor

@matinlotfali matinlotfali commented Apr 10, 2026

gpio_pin_is_valid() and gpio_pin_is_output_capable() use BIT() which
expands to (1UL << n). On 32-bit Xtensa targets, unsigned long is
32 bits, so BIT(n) for n >= 32 is undefined behavior.

This causes gpio1 pins (GPIO32+) to always fail validation with
-EINVAL, breaking any peripheral connected to GPIO32-GPIO48 on
ESP32-S3 (and similar ESP32 variants with gpio1).

Fix by using BIT64() which correctly handles pin numbers >= 32
since SOC_GPIO_VALID_GPIO_MASK is already a 64-bit value.

Note that correct devicetree addressing (&gpio1 N instead of &gpio0 (N+32))
does not work around this bug. gpio_esp32_config() converts the
port-relative pin to an absolute GPIO number (io_pin = pin + 32 for gpio1)
before passing it to gpio_pin_is_valid(io_pin), so the BIT() overflow
still occurs regardless of how the pin is addressed in the devicetree.

The bug may appear intermittent because the result of 1UL << N for N >= 32
is undefined — at runtime on Xtensa hardware the shift amount wraps
(N & 31, producing a non-zero value that passes the check), but when GCC
constant-folds the expression at compile time with optimizations enabled,
it can produce 0, causing the validation to fail.

Related: #65244

gpio_pin_is_valid() and gpio_pin_is_output_capable() use BIT() which
expands to (1UL << n). On 32-bit Xtensa targets, unsigned long is
32 bits, so BIT(n) for n >= 32 is undefined behavior.

This causes gpio1 pins (GPIO32+) to always fail validation with
-EINVAL, breaking any peripheral connected to GPIO32-GPIO48 on
ESP32-S3 (and similar ESP32 variants with gpio1).

Fix by using BIT64() which correctly handles pin numbers >= 32
since SOC_GPIO_VALID_GPIO_MASK is already a 64-bit value.

Signed-off-by: Matin Lotfaliei <matinlotfali@gmail.com>
@sylvioalves
Copy link
Copy Markdown
Contributor

@matinlotfali please, would you also fix the pinctrl_esp32.c file?
https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/pinctrl/pinctrl_esp32.c#L69
https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/pinctrl/pinctrl_esp32.c#L74

Thanks!

Same issue as the GPIO driver: esp32_pin_is_valid() and
esp32_pin_is_output_capable() use BIT() which overflows on 32-bit
Xtensa for pin numbers >= 32.

Fix by using BIT64() to match the 64-bit SOC_GPIO_VALID_GPIO_MASK.

Signed-off-by: Matin Lotfaliei <matinlotfali@gmail.com>
@matinlotfali
Copy link
Copy Markdown
Contributor Author

@sylvioalves done

@sonarqubecloud
Copy link
Copy Markdown

@nashif nashif merged commit d53115b into zephyrproject-rtos:main Apr 15, 2026
28 of 29 checks passed
@matinlotfali matinlotfali deleted the fix/gpio-esp32-bit64-overflow branch April 15, 2026 06:02
@sylvioalves sylvioalves added the backport v4.4-branch Request backport to the v4.4-branch label Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: GPIO area: Pinctrl backport v4.4-branch Request backport to the v4.4-branch platform: ESP32 Espressif ESP32

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants