diff options
Diffstat (limited to '')
-rw-r--r-- | private/crt32/heap/heapchk.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/private/crt32/heap/heapchk.c b/private/crt32/heap/heapchk.c new file mode 100644 index 000000000..872b124d5 --- /dev/null +++ b/private/crt32/heap/heapchk.c @@ -0,0 +1,330 @@ +/*** +*heapchk.c - perform a consistency check on the heap +* +* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines the _heapchk() and _heapset() functions +* +*Revision History: +* 06-30-89 JCR Module created. +* 07-28-89 GJF Added check for free block preceding the rover +* 11-13-89 GJF Added MTHREAD support, also fixed copyright +* 12-13-89 GJF Added check for descriptor order, did some tuning, +* changed header file name to heap.h +* 12-15-89 GJF Purged DEBUG286 stuff. Also added explicit _cdecl to +* function definitions. +* 12-19-89 GJF Got rid of checks involving plastdesc (revised check +* of proverdesc and DEBUG errors accordingly) +* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h>. +* 03-29-90 GJF Made _heap_checkset() _CALLTYPE4. +* 09-27-90 GJF New-style function declarators. +* 03-05-91 GJF Changed strategy for rover - old version available +* by #define-ing _OLDROVER_. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <heap.h> +#include <malloc.h> +#include <os2dll.h> +#include <stddef.h> +#include <string.h> +#ifdef DEBUG +#include <stdio.h> +#endif + +static int _CALLTYPE4 _heap_checkset(unsigned int _fill); + +/* Debug error values */ +#define _EMPTYHEAP 0 +#define _BADROVER 1 +#define _BADRANGE 2 +#define _BADSENTINEL 3 +#define _BADEMPTY 4 +#define _EMPTYLOOP 5 +#define _BADFREE 6 +#define _BADORDER 7 + +#ifdef DEBUG + +static char *errmsgs[] = { + "_heap_desc.pfirstdesc == NULL", + "_heap_desc.proverdesc not found in desc list", + "address is outside the heap", + "sentinel descriptor corrupted", + "empty desc pblock != NULL (debug version)", + "header ptr found twice in emptylist", + "free block precedes rover", + "adjacent descriptors in reverse order from heap blocks" + }; + +#define _PRINTERR(msg) \ + printf("\n*** HEAP ERROR: %s ***\n", errmsgs[(msg)]); \ + fflush(stdout); + +#else /* !DEBUG */ + +#define _PRINTERR(msg) + +#endif /* DEBUG */ + + +/*** +*int _heapchk() - Validate the heap +*int _heapset(_fill) - Validate the heap and fill in free entries +* +*Purpose: +* Performs a consistency check on the heap. +* +*Entry: +* For heapchk() +* No arguments +* For heapset() +* int _fill - value to be used as filler in free entries +* +*Exit: +* Returns one of the following values: +* +* _HEAPOK - completed okay +* _HEAPEMPTY - heap not initialized +* _HEAPBADBEGIN - can't find initial header info +* _HEAPBADNODE - malformed node somewhere +* +* Debug version prints out a diagnostic message if an error is found +* (see errmsg[] above). +* +* NOTE: Add code to support memory regions. +* +*Uses: +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _heapchk(void) +{ + return(_heap_checkset((unsigned int)_HEAP_NOFILL)); +} + +/******************************************************************************/ + +int _CALLTYPE1 _heapset ( + unsigned int _fill + ) +{ + return(_heap_checkset(_fill)); +} + + +/*** +*static int _heap_checkset(_fill) - check the heap and fill in the +* free entries +* +*Purpose: +* Workhorse routine for both _heapchk() and _heapset(). +* +*Entry: +* int _fill - either _HEAP_NOFILL or a value to be used as filler in +* free entries +* +*Exit: +* See description of _heapchk()/_heapset() +* +*******************************************************************************/ + +static int _CALLTYPE4 _heap_checkset ( + unsigned int _fill + ) +{ + REG1 _PBLKDESC pdesc; + REG2 _PBLKDESC pnext; + int roverfound=0; + int retval = _HEAPOK; + + /* + * lock the heap + */ + + _mlock(_HEAP_LOCK); + + /* + * Validate the sentinel + */ + + if (_heap_desc.sentinel.pnextdesc != NULL) { + _PRINTERR(_BADSENTINEL); + retval = _HEAPBADNODE; + goto done; + } + + /* + * Test for an empty heap + */ + + if ( (_heap_desc.pfirstdesc == &_heap_desc.sentinel) && + (_heap_desc.proverdesc == &_heap_desc.sentinel) ) { + retval = _HEAPEMPTY; + goto done; + } + + /* + * Get and validate the first descriptor + */ + + if ((pdesc = _heap_desc.pfirstdesc) == NULL) { + _PRINTERR(_EMPTYHEAP); + retval = _HEAPBADBEGIN; + goto done; + } + + /* + * Walk the heap descriptor list + */ + + while (pdesc != &_heap_desc.sentinel) { + + /* + * Make sure address for this entry is in range. + */ + + if ( (_ADDRESS(pdesc) < _ADDRESS(_heap_desc.pfirstdesc)) || + (_ADDRESS(pdesc) > _heap_desc.sentinel.pblock) ) { + _PRINTERR(_BADRANGE); + retval = _HEAPBADNODE; + goto done; + } + + pnext = pdesc->pnextdesc; + + /* + * Make sure the blocks corresponding to pdesc and pnext are + * in proper order. + */ + + if ( _ADDRESS(pdesc) >= _ADDRESS(pnext) ) { + _PRINTERR(_BADORDER); + retval = _HEAPBADNODE; + goto done; + } + + /* + * Check the backpointer. + */ + + if (_IS_INUSE(pdesc) || _IS_FREE(pdesc)) { + + if (!_CHECK_PDESC(pdesc)) { + retval = _HEAPBADPTR; + goto done; + } + } + + /* + * Check for proverdesc + */ + + if (pdesc == _heap_desc.proverdesc) + roverfound++; + +#ifdef _OLDROVER_ + + /* + * If it is free, make sure it doesn't precede the rover + * block and fill it in if appropriate + */ + + if ( _IS_FREE(pdesc) ) { + + if ( roverfound == 0 ) { + _PRINTERR(_BADFREE); + retval = _HEAPBADNODE; + goto done; + } + + if ( _fill != _HEAP_NOFILL ) + memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE), + _fill, _BLKSIZE(pdesc) ); + } + +#else /* ndef _OLDROVER_ */ + + /* + * If it is free, fill it in if appropriate + */ + + if ( _IS_FREE(pdesc) && (_fill != _HEAP_NOFILL) ) + memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE), + _fill, _BLKSIZE(pdesc) ); + +#endif /* _OLDROVER_ */ + + /* + * Onto the next block + */ + + pdesc = pnext; + } + + /* + * Make sure we found 1 and only 1 rover + */ + + if (_heap_desc.proverdesc == &_heap_desc.sentinel) + roverfound++; + + if (roverfound != 1) { + _PRINTERR(_BADROVER); + retval = _HEAPBADBEGIN; + goto done; + } + + /* + * Walk the empty list. We can't really compare values against + * anything but we may loop forever or may cause a fault. + */ + + pdesc = _heap_desc.emptylist; + + while (pdesc != NULL) { + +#ifdef DEBUG + if (pdesc->pblock != NULL) { + _PRINTERR(_BADEMPTY) + retval = _HEAPBADPTR; + goto done; + } +#endif + + pnext = pdesc->pnextdesc; + + /* + * Header should only appear once + */ + + if (pnext == _heap_desc.emptylist) { + _PRINTERR(_EMPTYLOOP) + retval = _HEAPBADPTR; + goto done; + } + + pdesc = pnext; + + } + + + /* + * Common return + */ + +done: + /* + * release the heap lock + */ + + _munlock(_HEAP_LOCK); + + return(retval); + +} |