Cyan
Cyan

Reputation: 13978

Ensuring out-of-bound memory writes trigger an immediate fault

I just had a difficult time tracking a quite typical C bug, related to memory allocation. One of my buffers was one byte too short. As a consequence, one byte too much was written beyond its upper limit.

In most circumstances, it had no effect; but in some specific cases, it would result in a future operation to fail (typically a malloc, or a hidden malloc within another function).

What makes this kind of bug difficult to track is that they do not occur at the position where the error is, leading to bad initial diagnosis. And it also never happen in debugging mode, making the hunt even more difficult.

This kind of bug is pretty common in C, and a long standing weakness of the language.

So what could have helped there ?

Well, should the "one byte too much" write trigger an immediate fault, it would truly help, first to detect where is the problem, but also to detect that there is a problem at all ! (in the previous example, the bug passed all tests and reached production stage; nightmare situation...).

Does such a setting exists (in C) ? I'm guessing that if some solution exist, it's probably platform dependent. But of course, if a portable one exists, I'm even more interested.

[Edit] Thanks for the very good answers. I see there is no silver-bullet solution, but a set of tools to attenuate the issue. I'll need some time to study all the very good links provided in your answers.

Upvotes: 0

Views: 88

Answers (3)

lsk
lsk

Reputation: 532

There are tools available that would write a "red zone" area after the buffer. The red zone would contain a special keyword that can be periodically checked (like at free time, use time, etc) to determine the sanity of the buffer. This would only tell you if there is a problem....not who did it.

Another solution is to "page protect" the page immediately after the buffer. For example,

vaddr = mmap(2 pages); // buffer of 1 page, red zone 1 page
mprotect(vaddr+1 page, READ_ONLY);

This would trap any write access to the red zone page and help catch the culprit red-handed. Of course, afaik, the mprotect() needs an mmap'ed address and granularity is 1 page.

Upvotes: 1

cnicutar
cnicutar

Reputation: 182754

Triggering an immediate fault with a normal is probably difficult. There are alternatives to solve this however. My favorite is running the program under valgrind: any sort of funny business will be marked as an illegal read or an illegal write.

Here's a simple buggy program:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *p = malloc(10);
    p[10] = 42;

    return 0;
}

And here's what I get when running under valgrind:

==11551== Invalid write of size 1
==11551==    at 0x40052A: main (main.c:7) # <------ compile with debugging symbols
==11551==  Address 0x51b904a is 0 bytes after a block of size 10 alloc'd
==11551==    at 0x4C28BED: malloc (vg_replace_malloc.c:263)
==11551==    by 0x40051D: main (main.c:6)
==11551== 

Anything less intrusive probably has less granularity (i.e. it might miss some illegal accesses). The wiki page I linked has plenty of alternatives for various platforms.

Upvotes: 1

Scotty Bauer
Scotty Bauer

Reputation: 1277

You can use gcc's -Wstack-protector. And for debugging you can use mudflap.

Upvotes: 1

Related Questions