/* * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). * You may copy, distribute, and use this software as long as this * copyright statement is not removed. */ #include #include #include "malloc.h" /* * Function: malloc_chain_check() * * Purpose: to verify malloc chain is intact * * Arguments: todo - 0 - just check and return status * 1 - call malloc_warn if error detected * * Returns: 0 - malloc chain intact & no overflows * other - problems detected in malloc chain * * Narrative: * * Notes: If todo is non-zero the malloc_warn function, when called * may not return (i.e. it may exit) * */ #ifndef lint static char rcs_hdr[] = "$Id: mlc_chn.c,v 1.1 1992/01/24 03:29:10 dvadura Exp $"; #endif int malloc_chain_check(todo) int todo; { char * func = "malloc_chain_check"; int i; extern char * malloc_data_start; extern char * malloc_data_end; extern struct mlist * malloc_end; extern int malloc_errno; extern struct mlist malloc_start; struct mlist * oldptr; struct mlist * ptr; int rtn = 0; oldptr = &malloc_start; for(ptr = malloc_start.next; ; ptr = ptr->next) { /* * Since the malloc chain is a forward only chain, any * pointer that we get should always be positioned in * memory following the previous pointer. If this is not * so, we must have a corrupted chain. */ if( ptr ) { if(ptr < oldptr ) { malloc_errno = M_CODE_CHAIN_BROKE; if( todo ) { malloc_fatal(func); } rtn++; break; } oldptr = ptr; } else { if( oldptr != malloc_end ) { /* * This should never happen. If it does, then * we got a real problem. */ malloc_errno = M_CODE_NO_END; if( todo ) { malloc_fatal(func); } rtn++; } break; } /* * verify that ptr is within the malloc region... * since we started within the malloc chain this should never * happen. */ if( ((char *)ptr < malloc_data_start) || ((char *)ptr > malloc_data_end) ) { malloc_errno = M_CODE_BAD_PTR; if( todo ) { malloc_fatal(func); } rtn++; break; } /* * verify magic flag is set */ if( (ptr->flag&M_MAGIC) != M_MAGIC ) { malloc_errno = M_CODE_BAD_MAGIC; if( todo ) { malloc_warning(func); } rtn++; continue; } /* * verify segments are correctly linked together */ if( (ptr->prev && (ptr->prev->next != ptr) ) || (ptr->next && (ptr->next->prev != ptr) ) || ((ptr->next == NULL) && (ptr->prev == NULL)) ) { malloc_errno = M_CODE_BAD_CONNECT; if( todo ) { malloc_warning(func); } rtn++; continue; } /* * If this segment is allocated */ if( (ptr->flag & M_INUSE) != 0 ) { /* * verify no overflow of data area */ for(i=ptr->r_size; i < ptr->s.size; i++) { if( ptr->data[i] != M_FILL ) { malloc_errno = M_CODE_OVERRUN; if( todo ) { malloc_warning(func); } rtn++; break; } } } else /* it's not allocated so */ { /* * verify no reuse of freed data blocks */ for(i=0; i < ptr->s.size; i++) { if( ptr->data[i] != M_FREE_FILL ) { malloc_errno = M_CODE_REUSE; if( todo ) { malloc_warning(func); } rtn++; break; } } } } /* for(... */ return(rtn); } /* malloc_chain_check(... */