False positive for out of bound memory access on a microcontroller

Versions:
Sonarqube Enterprise = Version 8.9.9 (build 56886)
Sonar Scanner = 4.7.0.2747

I have a false-positive Out of bound memory access finding.

I am working on a project that creates firmware for a microcontroller. My code that causes a false positive looks like this:

void my_fxn(int index)
{
    if (index > MAX_INDEX)
    {
        error_handler(index)
    }

    int value = my_array[index]
}

This won’t be an error because of the error_handler() function. This function writes to some registers that causes the microcontroller to reset.

Is there a way to inform sonarqube these register writes act as an exit to the program?

Hello @daltonv,

One way to convey that information is by decorating the function error_handler with the [[ noreturn ]] attribute.

If you cannot change the declaration of this function, maybe you can ask your microcontroller provider to update it, but meanwhile, you can just wrap it in a function of your own that is declared with this attribute.

Hello JolyLoic,

Thanks this is a good idea!

Our error_handler() function already has a wrapper for the vendors function.

This is a plain C project so I have to use the gcc __attribute__((noreturn)) to decorate the function. However, when I add this attribute I now get a compiler warning warning: 'noreturn' function does return.

Maybe Sonarqube is actually telling me something useful here.

Maybe our wrapper should be:

__attribute__((noreturn)) void our_reset()
{
     vendor_reset();
     while(1) {}
}

I’m fairly certain we would never enter the while(1), but It might be safer than just blindly returning if the impossible happens.

Any other C embedded firmware engineers run into a similar situation? This seems like it would be a common problem in any bare metal application.

Regards,
Dalton

Another option is to use a known noreturn function that is available in your standard library. For example, exit:

__attribute__((noreturn)) void our_reset()
{
     vendor_reset();
     exit(0);
}

This way, if vendor_reset does accidentally return, you won’t be stuck in an infinite loop.