2

I've been bitten in the ass a few times where I would write to an array out of scope. I have been working on a particular firmware for over 2 years and suspect an overflow which by now is close to impossible to find - for example:

uint8_t example[50];
uint8_t example2[100];
for(uint8_t i = 0; i < sizeof(example2); i++)
   example[i] = i;

I understand that the above code example is primitive. It's only an example of what I am trying to describe.

Is there a package or function available that can detect these "leaks"?

glts
  • 21,808
  • 12
  • 73
  • 94
  • 1
    For embedded systems, MISRA-C checkers (static analysis) seems to be the most popular option, since many systems need to conform with MISRA-C anyway. – Lundin Feb 21 '22 at 09:16

4 Answers4

2

Recent versions of GCC with the flag -Wall will detect simple errors like the problem in your example, and print a warning.

The tool Valgrind is more advanced, but also more work to configure and use correctly.

There is no tool in the universe that can detect every possible mistake, so start with the easiest to use.

Tom V
  • 4,827
  • 2
  • 5
  • 22
  • 2
    Valgrind is mildly useful for embedded systems since it's a dynamic analyser for PC. You'll want a static analyser or a dynamic one for the target system. – Lundin Feb 21 '22 at 09:14
  • 1
    @user17732522 it does for me: https://godbolt.org/z/9s4TfYGPT – Tom V Feb 21 '22 at 13:42
  • 1
    @TomV Ah, right. I forgot that these warnings only work with optimizations enabled. – user17732522 Feb 21 '22 at 13:44
2

Static analysis can only do so much, but here are a couple of the tools I'm using on a daily basis:

  • cppcheck
  • clang-tidy (part of LLVM) - not trivial to set up if you don't use CMake.

Also, as Tom V pointed out, turn on as many warnings as possible (-Wall is a minimum - here is a good starting set of warning flags).

Armandas
  • 2,276
  • 1
  • 22
  • 27
2

The tool Frama-c , through the Eva plugin, allows to do value analysis: it is able to compute every possible value for each variable and then detects (among other issues) array overflows even in non trivial code source.

Guillaume Petitjean
  • 2,408
  • 1
  • 21
  • 47
1

GCC warns about out-of-bound issues like this. Compiling this code example with -Wall -pedantic -O1:

int main(void) {
    int example[50];
    for (int i = 0; i < 100; i++)
        example[i] = i;
    return example[0];
}

...results in this compilation warning (using ARM GCC 11.2 (linux), testable here on Godbolt, like already pointed out in the comments of Tom V's answer):

<source>: In function 'main':
<source>:4:20: warning: iteration 50 invokes undefined behavior [-Waggressive-loop-optimizations]
    4 |         example[i] = i;
      |         ~~~~~~~~~~~^~~
<source>:3:23: note: within this loop
    3 |     for (int i = 0; i < 100; i++)
      |                     ~~^~~~~
Compiler returned: 0

In this case, the optimization option flag -O1 (or -O2, -Os) is required to get the undefined behavior warning from GCC. -O3 optimizes the loop out, so there will be no warning. No optimization (default option -O0) also results in no warning, because GCC apparently only notices the out-of-bound issue when it's optimizing the loop (see -Waggressive-loop-optimizations), as far as I can tell.

(Some notes: GCC's -fstack-check and -fstack-protector options might also be worth a look (runtime checks). Valgrind or other static/dynamic analysis tools can also be useful. However, on microcontrollers it is often not that easy to analyze the program at runtime on the target, an emulator or compiling the non-platform specific parts of the program with different compilers right on the development machine can help as well, to make it more rigid.

Related topics have been discussed here: Accessing an array out of bounds gives no error, why?, How does the gcc option -fstack-check exactly work?)

rel
  • 764
  • 5
  • 18