Interpreting Mudflap output

The errors that Mudflap detects include buffer overflows and underflows, and memory leaks. These errors are presented in the Mudflap Violations view, as follows:

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:
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
This information from the console for the example above can be explained as follows:
  • mudflap violation 1 (unregister): time=1238449399.353085 ptr=0x804a4b0 
         size=0
    This output refers to the first violation encountered by Mudflap for the example. It was attempting to deallocate a memory object with base pointer 0x804a4b0. The timestamp can be decoded as 353 milliseconds on Monday March 30.
  • 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]
    The pointer access occurred at the given PC value in the instrumented program, which is associated with the project AQNXCProject in the main function. The libmudflapth.so.0 lines provide a few levels of stack backtrace information, including PC values in square brackets, and occasionally module and function names.
  • Nearby object 1: checked region begins 0B into and ends 0B into

    There was an object near the accessed region, and in fact, the access is entirely within the region, referring to its byte #0.

  • mudflap object 0x8055500: name=`string literal' 
    bounds=[0x804a4b0,0x804a4b0] size=1 area=static check=0r/0w liveness=0

    The result indicates a string literal, and the object has the specified bounds and size. The check part indicates that it has not been read (0r for this current access), and never written (0w). The liveness portion of the results relates to an assessment of how frequently this object has been recently accessed; in this case, no access.

    If the result indicated a malloc region, then the object would have been created by the malloc wrapper on the heap.

  • 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]

    The moment of allocation for this object is described by the time and stack backtrace. If this object was also deallocated, there would be a similar deallocation clause. Because a deallocation clause doesn't exist, this means that the object is still alive, or available to access.

To summarize the information above: Some code in the main function for the AQNXCProject project contains an illegal deallocation of memory because an operation is performed on a pointer that doesn't point to an appropriate heap segment (i.e., an allocated block that has not yet been 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:
    • Your program tells the system to free a memory block that has already been freed, thereby causing a subsequent reference to pick up an invalid pointer. You 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.
    • You perform a free operation on a pointer that doesn't point to an appropriate heap memory block, which results in illegal deallocation of memory. This type of error can occur when you free a pointer to stack or static memory or to heap memory but not the beginning of an allocated block, or you perform a free more than once on the same memory location.

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

      To address the illegal deallocation of memory, you can:
      • 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 right after deallocation, unless it's a local variable that goes out of scope
      Note: If you need to iterate over allocated memory, use another pointer (i.e., an alias) or an index.
      The following code demonstrates a bad free operation:
      #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 error occurs when a program writes to a memory area that's out of bounds for the buffer it intended to write to, which in turn generates memory corruption (with an unpredictable failure in the future) and segmentation fault runtime errors.

    The following sample code shows a buffer overflow:
    #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 from or write to memory that was previously freed. The result is a conflict and the program generates a memory error. For example, if a program calls the free function for a particular heap block, but continues to use that block, it will create a reuse problem when a malloc call is made. Using freed memory generates memory corruption (resulting in an unpredictable future failure) or random data read errors (when the heap is re-used, other data can be in that location).

    The following code demonstrates 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 array elements that don't exist (likely due to a bad index value).

    The following code shows an example of an out-of-bounds read:
    #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>) — the most common memory leak case is when heap memory is not deallocated.

    The following code shows an example of a heap 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 but don't forget to free  
            // and NULL the pointer; otherwise, the memory is leaked
        }
    
        return 0;
    }