summaryrefslogtreecommitdiffstats
path: root/private/crt32/heap/heapchk.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/heap/heapchk.c')
-rw-r--r--private/crt32/heap/heapchk.c330
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);
+
+}