The type of errors that Mudflap detects includes overflow/underflow (running off the ends of buffers and strings) and memory leaks.
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; }
Sample Mudflap outputs results in the Mudflap Violations view.
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.7-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:
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 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 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:
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.
The following code shows an example of a buffer overflow:
int main(int argc, char ** argv){ char * str = ""; if (argc>1) { str = malloc(10); // ... } printf("Str: %s\n",str); free(str); return 0; }
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; }
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; }
For example, the following code shows an example of a memory leak:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char ** argv){ char * str = malloc(10); if (argc>1) { str = malloc(20); // ... } printf("Str: %s\n",str); free(str); return 0; }
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 memory but // don't forget to free and NULL the pointer } return 0; }