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.
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 4: Schematic showing the relative layout in memory of the block and the corrupted guard zone.
  • Line 7: Range of corrupted memory showing the guard zone, the expected memory pattern, and the pattern that was found instead.
  • Line 11: The memory block that is most likely the one that has been corrupted and the stack trace of its allocation.
  • Line 15: The stack trace where the memory was freed, (may or may not be present).
  • Line 18: The stack trace showing the call sequence to the error.
  • Line 21: 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().

  • No labels