The compilers, discover, and uncover find static code issues, dynamic memory access issues, and coverage issues in your code. This appendix describes the specific error types that are found by these tools and analyzed by Code Analyzer.
Code coverage checking determines which functions are uncovered. In the results, code coverage issues found are labeled as Uncovered Function, with a potential coverage percentage, indicating the percentage of coverage that will be added to the total coverage for the application if a test covering the relevant function is added.
Possible Causes: No test might execute your function or you might have forgotten to delete dead or old code.
Static code checking finds the following types of errors:
ABR: beyond array bounds read
ABW: beyond array bounds write
DFM: double freeing memory
ECV: explicit type cast violation
FMR: freed memory read
FMW: freed memory write
INF: infinite empty loop
MLK: memory leak
MFR: missing function return
MRC: missing malloc return value check
NFR: uninitialized function return
NUL: null pointer dereference, leaky pointer check
RFM: return freed memory
UMR: uninitialized memory read, uninitialized memory read bit operation
URV: unused return value
VES: out-of-scope local variable usage
This section describes possible causes of the error and a code example of when the error might occur.
Possible causes: Attempting to read memory beyond the array bounds.
Example:
int a[5]; . . . printf("a[5] = %d\n",a[5]); // Reading memory beyond array bounds
Possible causes: Attempting to write memory beyond the array bounds.
Example:
int a [5]; . . . a[5] = 5; // Writing to memory beyond array bounds
Possible Causes: Calling free()() more than once with the same pointer. In C++, using the delete operator more than once on the same pointer.
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // p was not signed a new value between the free statements free(p); // Double freeing memory
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // Nothing assigned to p in between printf("p = 0x%h\n",p); // Reading from freed memory
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // Nothing assigned to p in between *p = 1; // Writing to freed memory
Example:
int x=0; int i=0; while (i200) { x++; } // Infinite loop
Possible causes: Memory is allocated but not freed before exit or escaping from the function.
Example:
int foo() { int *p = (int*) malloc(sizeof(int)); if (x) { p = (int *) malloc(5*sizeof(int)); // will cause a leak of the 1st malloc } } // The 2nd malloc leaked here
Possible causes: Missing return values along some paths to exit.
Example:
#include <stdio.h> int foo (int a, int b) { if (a) { return b; } } // If foo returns here, the return is uninitialized int main ( ) { printf("%d\n", foo(0,30)); }
Possible causes: Accessing a return value from malloc in C or a new operator in C++ without checking against null.
Example:
#include <stdlib.h> int main() { int *p3 = (int*) malloc(sizeof(int)); // Missing null-pointer check after malloc. *p3 = 0; }
Possible causes: Accessing a pointer that might equal to null, or redundant checking against null in case the pointer is never null.
Example:
#include <stdio.h> #include <stdlib.h> int gp, ctl; int main() { int *p = gp; if (ctl) p = 0; printf ("%c\n", *p); // May be null pointer dereference if (!p) *p = 0; // Surely null pointer dereference int *p2 = gp; *p2 = 0; // Access before checking against NULL. assert (p2!=0); int *p3 = gp; if (p3) { printf ("p3 is not zero.\n"); } *p3 = 0; // Access is not protected by previous check against NULL. }
Example:
#include <stdlib.h> int *foo () { int *p = (int*) malloc(sizeof(int)); free(p); return p; // Return freed memory is dangerous } int main() { int *p = foo(); *p = 0; }
Possible causes: Reading local or heap data that has not been initialized.
Example:
#include <stdio.h> #include <stdlib.h> struct ttt { int a: 1; int b: 1; }; int main() { int *p = (int*) malloc(sizeof(int)); printf("*p = %d\n",*p); // Accessing uninitialized data struct ttt t; extern void foo (struct ttt *); t.a = 1; foo (&t); // Access uninitialized bitfield data "t.b" }
Possible causes: Reading local or heap data that has not been initialized.
Example:
int foo(); int main() { foo(); // Return value is not used. }
Possible causes: Reading local or heap data that has not been initialized.
Example:
int main() { int *p = (int *)0; void bar (int *); { int a[10]; p = a; } // local variable 'a' leaked out bar(p); }
Dynamic memory access checking finds the following types of errors:
ABR: beyond array bounds read
ABW: beyond array bounds write
BFM: bad free memory
BRP: bad realloc address parameter
CGB: corrupted guard block
DFM: double freeing memory
FMR: freed memory read
FMW: freed memory write
FRP: freed realloc parameter
IMR: invalid memory read
IMW: invalid memory write
MLK: memory leak
OLP: overlapping source and destination
PIR: partially initialized read
SBR: beyond stack bounds read
SBW: beyond stack bounds write
UAR: unallocated memory read
UAW: unallocated memory write
UMR: uninitialized memory read
This sections describes the possible causes of the error and a code example of when the error would occur.
Possible causes: Attempting to read memory beyond the array bounds.
Example:
int a[5]; . . . printf("a[5] = %d\n",a[5]); // Reading memory beyond array bounds
Possible causes: Attempting to write memory beyond the array bounds.
Example:
int a [5]; . . . a[5] = 5; // Writing to memory beyond array bounds
Possible Causes: Passing a non-heap data pointer to free()() or realloc()().
Example:
#include <stdlib.h> int main() { int *p = (int*) malloc(sizeof(int)); free(p+1); // Freeing wrong memory block }
Example:
#include <stdlib.h> int main() { int *p = (int*) realloc(0,sizeof(int)); int *q = (int*) realloc(p+20,sizeof(int[2])); // Bad address parameter for realloc }
Possible Causes: Writing past the end of a dynamically allocated array, or being in the "red zone".
Example:
#include <stdio.h> #include <stdlib.h> int main() { int *p = (int *) malloc(sizeof(int)*4); *(p+5) = 10; // Corrupted array guard block detected (only when the code is not annotated) free(p); return 0; }
Possible Causes: Calling free()() more than once with the same pointer. In C++, using the delete operator more than once on the same pointer.
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // p was not assigned a new value between the free statements free(p); // Double freeing memory
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // Nothing assigned to p in between printf("p = 0x%h\n",p); // Reading from freed memory
Example:
int *p = (int*) malloc(sizeof(int)); free(p); . . . // Nothing assigned to p in between *p = 1; // Writing to freed memory
Example:
#include <stdlib.h> int main() { int *p = (int *) malloc(sizeof(int)); free(0); int *q = (int*) realloc(p,sizeof(it[2])); //Freed pointer passed to realloc }
Possible causes: Reading 2, 4, or 8 bytes from an address that is not half-word aligned, word aligned, or double-word aligned, respectively.
Example:
#include <stdlib.h> int main() { int *p = 0; int i = *p; // Read from invalid memory address }
Possible causes: Writing 2, 4, or 8 bytes from an address that is not half-word aligned, word aligned, or double-word aligned, respectively. Writing to a text address, writing to a read-only data section (.rodata), or writing to a page that mmap has made read-only.
Example:
int main() { int *p = 0; *p = 1; // Write to invalid memory address }
Possible causes: Memory is allocated but not freed before exit or escaping from the function.
Example:
int foo() { int *p = (int*) malloc(sizeof(int)); if (x) { p = (int *) malloc(5*sizeof(int)); // will cause a leak of the 1st malloc } } // The 2nd malloc leaked here
Possible causes: Incorrect source, destination, or length is specified. When the source and destination overlap, the behavior of the program is undefined.
Example:
#include <stlib.h> #include <string.h> int main() { char *s=(char *) malloc(15); memset(s, 'x', 15); memcpy(s, s+5, 10); return 0; }
Example:
#include <stdio.h> #include <stdlib.h> int main() { int *p = (int*) malloc(sizeof(int)); *((char*)p) = 'c'; printf("*(p = %d\n",*(p+1)); // Accessing partially initialized data }
Possible causes: Reading a local array past the end or before the start.
Example:
#include <stdio.h> int main() { int a[2] = {0, 1}; printf("a[-10]=%d\n",a[-10]); // Read is beyond stack frame bounds return 0; }
Possible causes: Writing to a local array past the end or before the start.
Example:
#include <stdio.h> int main() { int a[2] = {0, 1}; a[-10] = 2; // Write is beyond stack frame bounds return 0; }
Possible causes: A stray pointer, overflowing the bounds of a heap block, or accessing a heap block that has already been freed.
Example:
#include <stdio.h> #include <stdlib> int main() { int *p = (int*) malloc(sizeof(int)); printf("*(p+1) = %d\n",*(p+1)); // Reading from unallocated memory }
Possible causes: A stray pointer, overflowing the bounds of a heap block, or accessing a heap block that has already been freed.
Example:
#include <stdio.h> #include <stdlib> int main() { int *p = (int*) malloc(sizeof(int)); *(p+1) = 1; // Writing to unallocated memory }
Possible causes: Reading local or heap data that has not been initialized.
Example:
#include <stdio.h> #include <stdlib> int main() { int *p = (int*) malloc(sizeof(int)); printf("*p = %d\n",*p); // Accessing uninitialized data }
Dynamic memory access checking finds the following types of warnings:
AZS: allocating zero size
Memory leak
SMR: speculative uninitialized memory read
This section describes the possible causes of the warning and a code example of when the warning might occur.
Example:
#include <stdlib> int main() { int *p = malloc(); // Allocating zero size memory block }
Possible causes: Memory is allocated but not freed before exit or escaping from the function.
Example:
int foo() { int *p = (int*) malloc(sizeof(int)); if (x) { p = (int *) malloc(5*sizeof(int)); // will cause a leak of the 1st malloc } } // The 2nd malloc leaked here
Example:
int i; if (foo(&i) != 0) /* foo returns nonzero if it has initialized i */ printf("5d\n", i);
The compiler might generate the following equivalent code for the above source:
int i; int t1, t2' t1 = foo(&i); t2 = i; /* value in i is loaded. So even if t1 is 0, we have uninitialized read due to speculative load */ if (t1 != 0) printf("%d\n", t2);