Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, how to detect boundary write error in free() function implementation?

Tags:

c

A boundary error is when a program reads or writes memory beyond the actual dimensions of an allocated memory block. An example boundary write error is to write the 11th entry in an array of size 10

I have a test that must detect boundary write error in my_free() function implementation

 int main()
 {   
   const char* string1 = "Hello, this is a string! I exist to demonstrate a common error.";
   char* copy_of_string1 = (char*) my_malloc(strlen(string1));

  // Whoops! Forgot to allocate space for the '\0' that ends the string.
   strcpy(copy_of_string1, string1); // == boundary write error
   my_free(copy_of_string1);

   return 0;
 }

How to catch the case where the user writes one or more zero bytes directly after the allocated block ?

like image 836
Anatoly Avatar asked Apr 09 '15 17:04

Anatoly


1 Answers

The common practice is to allocate some more memory than required and put a marker at the end (in the overallocated memory). When freeing, you will check that the marker has not been overwritten.

For myself I've created a custom version of malloc() which puts a marker both at the beginning and at the end of a block:

      +--------+
      |  size  |
      |BEEFF00D|
  p-> |  ...   |
      |DEADC0DA|
      +--------+

and will return p rather than the really allocated block.

When I free() the block I check that right before the pointer there is the value 0xBEEFF00D and if not, the pointer to be freed is not valid. Then, if it's valid, I check the end of the block (of which I've stored the size) and see if the marker 0xDEADC0DA is there, if not there has been an out of boundary error.

If everything is fine, before freeing up the (real) block I replace the initial marker 0xBEEFF00D with the marker 0xDEFACED so to catch double free() errors.

I've set everything up so that I can include an header and compile with the symbol UTL_MEMCHECK to make so that every free(), malloc(), calloc(), realloc() and strdup() will be replaced by my checking version. When I'm sure everything is fine, I'll recompile without UTL_MEMCHECK defined. This might be too overkill for you, but if you interested you can find my code here: https://github.com/rdentato/clibutl/blob/master/src/utl.h

Just jump around line 875 and ignore the rest.

like image 104
Remo.D Avatar answered Oct 03 '22 01:10

Remo.D