Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Out of bounds memory write in nrfx_gpiote_in_uninit with new pin

The following code has an unexpected out-of-bounds array access:

#define DRDY_PIN 24

nrfx_gpiote_in_uninit(DRDY_PIN);
nrfx_gpiote_in_init(DRDY_PIN, &drdy_cfg,onDRDY_gpiote_evt);

Primary cause is this line:

channel_free((uint8_t)channel_port_get(pin));

On an uninitalized pin number, channel_port_get() returns -1, which is converted to 255 via the cast and this causes out of bounds access in channel_free() - as the latter function does not check its argument for overflows.

Fix is pretty simple:

static void channel_free(uint8_t channel_id)
{
    if (channel_id >= 
      (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS)) return;
    m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;

Edit: This is using nRF SDK 16.0 version.

Parents
  • also happens in SDK 17.0.2 and SDK 15.3

    should modify nrfx_gpiote_in_uninit from this

    void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
    {
        NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
        NRFX_ASSERT(pin_in_use_by_gpiote(pin));
        nrfx_gpiote_in_event_disable(pin);
        if (pin_in_use_by_te(pin))
        {
            nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
        }
        if (pin_configured_check(pin))
        {
            nrf_gpio_cfg_default(pin);
            pin_configured_clear(pin);
        }
        channel_free((uint8_t)channel_port_get(pin));
        pin_in_use_clear(pin);
    }

    to this

    void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
    {
        NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
        NRFX_ASSERT(pin_in_use_by_gpiote(pin));
        nrfx_gpiote_in_event_disable(pin);
        if (pin_in_use_by_te(pin))
        {
            nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
        }
        if (pin_configured_check(pin))
        {
            nrf_gpio_cfg_default(pin);
            pin_configured_clear(pin);
        }
        if ( pin_in_use(pin) )
        {
            channel_free((uint8_t)channel_port_get(pin));
            pin_in_use_clear(pin);
        }
    }
    

Reply
  • also happens in SDK 17.0.2 and SDK 15.3

    should modify nrfx_gpiote_in_uninit from this

    void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
    {
        NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
        NRFX_ASSERT(pin_in_use_by_gpiote(pin));
        nrfx_gpiote_in_event_disable(pin);
        if (pin_in_use_by_te(pin))
        {
            nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
        }
        if (pin_configured_check(pin))
        {
            nrf_gpio_cfg_default(pin);
            pin_configured_clear(pin);
        }
        channel_free((uint8_t)channel_port_get(pin));
        pin_in_use_clear(pin);
    }

    to this

    void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
    {
        NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
        NRFX_ASSERT(pin_in_use_by_gpiote(pin));
        nrfx_gpiote_in_event_disable(pin);
        if (pin_in_use_by_te(pin))
        {
            nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
        }
        if (pin_configured_check(pin))
        {
            nrf_gpio_cfg_default(pin);
            pin_configured_clear(pin);
        }
        if ( pin_in_use(pin) )
        {
            channel_free((uint8_t)channel_port_get(pin));
            pin_in_use_clear(pin);
        }
    }
    

Children
No Data
Related