3

Are there any tools or methods that can identify buffer overruns in statically defined arrays (ie. char[1234] rather than malloc(1234))?

I spent most of yesterday tracking down crashes and odd behaviour which ultimately turned out to be caused by the following line:

// ensure string is nul terminated due to stupid snprintf
error_msg[error_msg_len] = '\0';

This index obviously caused writing beyond the bounds of the array. This lead to the clobbering of a pointer variable, leading to unexpected behaviour with that pointer later on.

The three things that come to mind that could help alleviate such problems are:

  1. Code review

    This wasn't done, but I'm working on that.

  2. valgrind

    I often use valgrind during development to detect memory problems but it does not deal with static arrays. In the above instance it only showed me the symptoms such as the invalid free() of the clobbered pointer.

  3. -fstack-protector-all

    In the past I have used -fstack-protector-all to detect overruns like the above but for some odd reason it didn't flag anything in this instance.

So can anyone offer any ideas on how I could identify such overruns? Either by improving on the above list or something completely new.

EDIT: Some of the answers so far have mentioned commercial products that are fairly expensive. At this stage I don't think I could convince the powers that be to buy such a tool so I'd like to restrict tools to cheap/free. Yes, you get what you pay for but some improvement is better than none.

Community
  • 1
  • 1
Burhan Ali
  • 2,258
  • 1
  • 28
  • 38
  • 1
    I know it's not relevant to the question asked, but `snprintf` does nul-terminate. – Steve Jessop Jan 27 '12 at 17:06
  • I have used Coverity to catch these errors, it's an excellent static analysis tool. However it is not free (or cheap) – TJD Jan 27 '12 at 17:19
  • @Steve Jessop Good point. It's `sprintf` that would need that sort of protection if you somehow wrote more than the available buffer size (which is a problem in itself). So it turns out that not only did that line have a buffer overrun, but it was also pointless. Boo. – Burhan Ali Jan 27 '12 at 17:26
  • @Burhan: the author of the code was probably confusing it with `strncpy`, which doesn't write a nul byte to the destination unless it finds it in the source before it hits the destination size limit. – Steve Jessop Jan 30 '12 at 11:10

3 Answers3

3

Static analyzer tools are able to detect some buffer overflows.

For example with this code:

char bla[1024];
int i;

for (i = 0; i <= 1024; i++)
    bla[i] = 0;

Here is what PC-Lint / flexelint reports:

tst.c 9 Warning 661: Possible access of out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference: file tst.c: lines 8, 9]

ouah
  • 142,963
  • 15
  • 272
  • 331
  • +1, but just make sure you read the 'living with lint' chapter at the start of the manual or expect to get inundated with messages. – SmacL Jan 27 '12 at 16:47
  • @ShaneMacLaughlin yes, that's the issue with static analyzers, they can be very verbose and reading their output report can take a lot of time. – ouah Jan 27 '12 at 16:49
  • @ouah `flexelint` seems to be for pay. I'm not sure I can convince the powers that be to do that right now so are there any other static analysers that you have tried and could recommend? – Burhan Ali Feb 02 '12 at 17:36
1

Have you tried the experimental Valgrind tool "SGCheck: an experimental stack and global array overrun detector" as opposed to the default "memcheck" tool?

http://valgrind.org/docs/manual/sg-manual.html

I haven't tried it myself but it appears to cover some of the types of bugs you are interested in.

Obviously, Valgrind does dynamic rather than static analysis which is a whole other discussion in itself.

Sam Elstob
  • 76
  • 1
  • 2
0

Our CheckPointer tool is a dynamic analysis tool that will catch out-of-bounds errors on arrays no matter where they are.

CheckPointer catches many things Valgrind cannot, e.g., references outside of any struct or struct field regardless of where allocated, including static arrays as in the problem shown by OP. Valgrind can't detect such overruns, because it has no clue about the actual shape of the data being manipulated; this requires an understanding of the programming langauge, e.g., C. Valgrind can only detect references outside of allocated memory. Checkpointer can do this because it understands C intimately; it uses a full compiler-style C front end to collect type and critical size information.

It presently is available for C, but not yet for C++.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341