In this section:

Overview

This error is generated when a dynamic memory block has become corrupt. Usually, the corruption is the result of a WRITE_OVERFLOW or WRITE_BAD_INDEX. This error is most often detected as the memory is being returned to the system.

Insure++ uses guard zones around dynamically allocated memory to help detect heap corruption that is otherwise difficult or impossible to discover. This feature can be turned on or off in the .psrc file.

CodeDescriptionEnabledReportedPlatform
HEAP_CORRUPT

Dynamic memory heap is corrupt

(tick)RuntimeWindows/Unix


Problem

The following code will generate a WRITE_BAD_INDEX and a subsequent HEAP_CORRUPT:

/*
 *File: heapcrpt.c
 */

void scribble(char* p)
	{
		*p = ‘a’;
	}

int main()
	{
		char* string = (char*) malloc(10);
		scribble(string+10);
		free(string);
		return 0;
	}

Diagnosis at Runtime

[heapcrpt.c:14] **HEAP_CORRUPT**
>>		 free(string);
The heap is corrupt.

---- Associated Common Weakness Enumerations ----
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
CWE-122: Heap-based buffer overflow
CWE-415: Double free
CWE-416: Use after free
CWE-590: Free of memory not on the heap
CWE-786: Access of memory before start of buffer
CWE-787: Out-of-bounds write
CWE-788: Access of memory location after end of buffer
CWE-805: IBuffer access with incorrect length value

	bbbbbb
	| 10 | 16 |
	xggggggg
Guardzone		 : 0x0804b022 thru 0x0804b031 (16 bytes)
Expected	 (g) : fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Found		 (x) : 61 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
			a . . . . . . . . . . . . . . .
Near Block (b) : 0x0804b018 thru 0x0804b021 (10 bytes)
			string, allocated at heapcrpt.c, 12
					malloc() (interface)
					main() heapcrpt.c, 12
Stack trace where memory was freed:
					free() (interface)
					main() heapcrpt.c, 14
Stack trace where error was detected:
					free() (interface)
					main() heapcrpt.c, 14
 **Memory corrupted. Program may crash!!**
  • Line 2: Source line at which the problem was detected.
  • Line 3: Description of the problem.
  • Line 5-14: CWEs associated with this problem.
  • Line 16: Schematic showing the relative layout in memory of the block and the corrupted guard zone.
  • Line 19: Range of corrupted memory showing the guard zone, the expected memory pattern, and the pattern that was found instead.
  • Line 23: The memory block that is most likely the one that has been corrupted and the stack trace of its allocation.
  • Line 27: The stack trace where the memory was freed, (may or may not be present).
  • Line 30: The stack trace showing the call sequence to the error.
  • Line 33: Informational message indicating that a serious error has occurred, which may cause the program to crash.

Repair

Look for previous WRITE_OVERFLOW or WRITE_BAD_INDEX errors—they might lead you to this particular error. If there aren't any, that means that the heap became corrupt in some uninstrumented code. Carefully examine all functions in all of the stack back traces to try to find the source of the problem.

Use a debugger to set a break point at the allocation location, then a watchpoint on the guardzone area which became corrupt. For example, in the sample code above, a watchpoint could be set on the memory at address 0x804b022. When the breakpoint "fires", you've found the bug.

The following example uses Linux's gcc and gdb:

$ insure gcc -g -Zoi 'function_ignore scribble' heapcrpt.c -o heapcrpt
	/"-Zoi 'function_ignore scribble'", causes the function "scribble()"
to be ignored -- ie: no instrumentation will be generated for it./
$ ./heapcrpt
[heapcrpt.c:14] **HEAP_CORRUPT**
>>	 free(string);
The heap is corrupt.
bbbbbb
	| 10 | 16 |
			xggggggg
Guardzone	 : 0x0804b022 thru 0x0804b031 (16 bytes)
Expected (g) : fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Found (x)	 : 61 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
				a . . . . . . . . . . . . . . .
Near Block (b) : 0x0804b018 thru 0x0804b021 (10 bytes)
				string, allocated at heapcrpt.c, 12
					malloc() (interface)
						main() heapcrpt.c, 12
stack trace where memory was freed:
					free() (interface)
					main() heapcrpt.c, 14
Stack trace where error was detected:
					free() (interface)
					main() heapcrpt.c, 14
**Memory corrupted. Program may crash!!**
$

To figure out what happened, look at GDB:

$ gdb heapcrpt
(gdb) b heapcrpt.c:12
(gdb) r
Breakpoint 1, main () at heapcrpt.c:12
12		char* string = (char*) malloc(10);

The memory is about to be allocated. Be sure that it's getting allocated correctly:

(gdb) n
13		 scribble(string+10);
(gdb) p/x *(char*)0x0804b022
$1 = 0xfa

If the guard zone has the right pattern in it (as shown above), set a watchpoint on this memory location:

(gdb) watch *(int*)0x0804b022
Hardware watchpoint 1: *(int *) 134524962
(gdb) c
Hardware watchpoint 1: *(int *) 134524962
Old value = -84215046
New value = -84215199
scribble (p=0x804b022 "a", 'ú' <repeats 15 times>) at heapcrpt.c:8
8 }

If you examine the source code immediately before the location where the watchpoint stopped, you can see the following:

(gdb) list

*/

void scribble(char* p)
{
	*p = 'a';
}

The code shows that the memory became corrupt on line 7. To examine the backtrace to see how you got there:

(gdb) bt
#0 scribble (p=0x804b022 "a", 'ú' <repeats 15 times>) at heapcrpt.c:8
#1 0x08049008 in main () at heapcrpt.c:13

Careful examination of line 13 of the file heapcrpt shows the problem: Wrong string offset sent down to function scribble().

References

The table below shows Common Weakness Enumerations associated with this error.

CWEDescription
CWE-119Improper Restriction of Operations within the Bounds of a Memory Buffer
CWE-122Heap-based buffer overflow
CWE-415Double free
CWE-416Use after free
CWE-590Free of memory not on the heap
CWE-786Access of memory before start of buffer
CWE-787Out-of-bounds write
CWE-788Access of memory location after end of buffer
CWE-805IBuffer access with incorrect length value
  • No labels