Interpreting Mudflap output

The type of errors that Mudflap detects includes overflow/underflow (running off the ends of buffers and strings) and memory leaks.

Figure 1. Sample Mudflap outputs results in the Mudflap Violations view.

For example, the following Mudflap output results are the result of an illegal deallocation of memory, which is illustrated by the following code segment:

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

int main(int argc, char ** argv){ 
   char * str = ""; 
   if (argc>1) { 
      str = malloc(10); 
      // ... 
      } 
   printf("Str: %s\n",str); 
   free(str); 
   return 0; 
}

The object name includes the name identified by Mudflap (i.e. if it's a local variable); otherwise, it can include the area, size and/or reference number (a pointer).

The output from the Console for this example looks like this:

[Console output redirected to file:C:\ide-4.8-workspace\AQNXCProject\
       output.mudflap] 
Str: ******* mudflap violation 1 (unregister): time=1238449399.353085
ptr=0x804a4b0 size=0 pc=0xb8207109, thread=1 
       libmudflapth.so.0(__mfu_unregister+0xa8) [0xb8206d2c]
       libmudflapth.so.0(__mf_unregister+0x3c) [0xb8207104]
       libmudflapth.so.0(__real_free+0xad) [0xb82091c9]
       AQNXCProject(main+0x41) [0x804902d] 
Nearby object 1: checked region begins 0B into and ends 0B into mudflap 
       object 0x8055500: name=`string literal' 
bounds=[0x804a4b0,0x804a4b0] size=1 area=static check=0r/0w liveness=0 
alloc time=1238449399.352085 pc=0xb8207593 thread=1 
number of nearby objects: 1 
Leaked object 1: 
mudflap object 0x8055290: name=`malloc region' 
bounds=[0x8055248,0x805525b] size=20 area=heap check=0r/0w liveness=0 
alloc time=1238449399.350085 pc=0xb8207593 thread=1 
       libmudflapth.so.0(__mf_register+0x3e) [0xb820758e] 
       libmudflapth.so.0(__real_malloc+0xba) [0xb8208b6a] 
       libc.so.3(atexit+0x19) [0xb032ac99]
       libc.so.3(_init_libc+0x33) [0xb03641b3] 
Leaked object 2:
mudflap object 0x8055360: name=`malloc region'
bounds=[0x8055318,0x805532b] size=20 area=heap check=0r/0w liveness=0 
alloc time=1238449399.351085 pc=0xb8207593 thread=1
       libmudflapth.so.0(__mf_register+0x3e) [0xb820758e]
       libmudflapth.so.0(__real_malloc+0xba) [0xb8208b6a]
       libc.so.3(atexit+0x19) [0xb032ac99] 
       AQNXCProject(_start+0x42) [0x8048f2a] 
Leaked object 3: 
mudflap object 0x8055430: name=`malloc region' 
bounds=[0x80553e8,0x80553fb] size=20 area=heap check=0r/0w liveness=0 
alloc time=1238449399.351085 pc=0xb8207593 thread=1 
       libmudflapth.so.0(__mf_register+0x3e) [0xb820758e] 
       libmudflapth.so.0(__real_malloc+0xba) [0xb8208b6a] 
       libc.so.3(atexit+0x19) [0xb032ac99]
       AQNXCProject(_start+0x61) [0x8048f49] 
Leaked object 4: 
mudflap object 0x80576a0: name=`malloc region'
bounds=[0x805a098,0x805a09f] size=8 area=heap check=0r/0w liveness=0 
alloc time=1238449399.352085 pc=0xb8207593 thread=1
       libmudflapth.so.0(__mf_register+0x3e) [0xb820758e]
       libmudflapth.so.0(__real_malloc+0xba) [0xb8208b6a]
       libc.so.3(_Initlocks+0x4c) [0xb0357aac]
       libc.so.3(__pthread_once+0x92) [0xb0320e32] 
Leaked object 5: mudflap object 0x8057708: name=`malloc region'
bounds=[0x8063bd8,0x8063fd7] size=1024 area=heap check=0r/0w liveness=0 
alloc time=1238449399.353085 pc=0xb8207593 thread=1
       libmudflapth.so.0(__mf_register+0x3e) [0xb820758e]
       libmudflapth.so.0(__real_malloc+0xba) [0xb8208b6a]
       libc.so.3(_Fbuf+0x4a) [0xb0352dea] 
       libc.so.3(_Fwprep+0x73) [0xb0353433] 
number of leaked objects: 5
And this information from the console for the example above can be explained as follows:

To summarize a conclusion for the information above, some code in the main() function for the project called AQNXCProject contains an illegal deallocation of memory because an operation is being performed on a pointer that doesn't point to an appropriate heap memory segment (a heap-allocated block that has not yet been properly deallocated). This situation is detected by the -internal-checking option.

Descriptions of Mudflap results

In the Mudflap Violations view, you might see errors similar to the following:
  • bad free (non-heap pointer) — this type of error occurs:
    • When a program attempts to tell the system to release a memory block that has already been freed, thereby causing a subsequent reference to pick up an invalid pointer. You'll need to locate the code where the actual error occurred, ensure that the size of the memory region is always accompanied by the pointer itself, verify all unsafe operations, and verify that the memory region is large enough to accommodate the data going into that location.
    • The illegal deallocation of memory occurs when you perform a free() operation on a pointer that doesn't point to an appropriate heap memory segment. This type of error can occur when you free a NULL pointer, free a pointer to stack or static memory, free a pointer to heap memory that doesn't point to the beginning of an allocated block, or perform a double free (when free()) is performed more than once on the same memory location).

      The illegal deallocation of memory can generate a memory corruption (a stack, heap, or static segment) or immediate segmentation fault runtime errors.

      To address the illegal deallocation of memory, you can: add a condition to test for a NULL as a pointer and verify that it can be freed; ensure that the same pointer can never point to different types of memory so that you don't free stack and static memory; never reassign an allocated pointer (except for a NULL or other allocation); nullify the pointer immediately after deallocation, unless it is a local variable that is out of scope.

      Note: If you need to iterate over allocated memory, use another pointer (alias), or just use an index.

      The following code shows an example:

      #include <stdio.h>
      #include <stdlib.h>
      #include <strings.h>
      
      main()
      {
          char foo[30];
      
          strcpy(foo, "hello world\n");
          printf("%s", foo);
          free(foo);  // error generated here
      }
  • write out of bounds violation — this type of buffer overflow error occurs when a program unintentionally writes to a memory area that's out of bounds for the buffer it intended to write to, which in turn generates the memory corruption (with an unpredictable failure in the future) and segmentation fault runtime errors.

    For example, the following code shows an example of a buffer overflow trapped by a library function:

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    int main(int argc, char ** argv){ 
       char * ptr = NULL; 
       ptr = malloc(12);
       strcpy(ptr,"This is a Mudflap example!"); 
       return 0; 
    }
  • write to unallocated memory (<type> violation) — occurs when you attempt to read or write to memory that was previously freed (using freed memory). The result will be a conflict and the program will generate a memory error. For example, if a program calls the free() function for a particular block, and then continues to use that block, it will create a reuse problem when a malloc() call is made. Using freed memory generates a memory corruption (results in an unpredictable future failure) or a random data read (when the heap is reused, other data can be in that location) runtime errors.

    For example, the following code shows an example of an uninitialized memory read.

    #include <stdio.h> 
    #include  <stdlib.h> 
    #include <string.h> 
    
    int main(int argc, char ** argv){ 
       char * ptr = NULL; 
       ptr = malloc(13);
       free(ptr); 
       strcpy(ptr,"This is a Mudflap example!"); 
       return 0; 
    }
  • read out of bounds (<type> violation) — occurs when an attempt is made to access the elements of an array that don't exist.

    For example, the following code shows an example of a memory leak:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        char charA[10];
        int i;
    
        for(i=0; i<10; i++)
            charA[i] = 'A';
    
        printf("value of out of bounds element of array: %c", charA[11]);
    
        return EXIT_SUCCESS;
    }
  • memory leak of size (<memorySize>) — the most common way that memory leak is created occurs when allocated memory is not deallocated.

    For example, the following code shows an example of a memory leak:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char ** argv){
        float *ptrFloat = (float*)malloc(444 * sizeof(float));
    
        if (ptrFloat==NULL) {
            // memory could not be allocated
        }
        else {
            // do something with the memory, then free it and set the
            // pointer to NULL 
        }
    
        return 0;
    }