home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dbmalloc.zip / mcheck.c < prev    next >
C/C++ Source or Header  |  1993-01-04  |  11KB  |  460 lines

  1.  
  2. /*
  3.  * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  4.  *
  5.  * This software may be distributed freely as long as the following conditions
  6.  * are met:
  7.  *         * the distribution, or any derivative thereof, may not be
  8.  *          included as part of a commercial product
  9.  *        * full source code is provided including this copyright
  10.  *        * there is no charge for the software itself (there may be
  11.  *          a minimal charge for the copying or distribution effort)
  12.  *        * this copyright notice is not modified or removed from any
  13.  *          source file
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "mallocin.h"
  18. #include "debug.h"
  19.  
  20. #ifndef lint
  21. static
  22. char rcs_hdr[] = "$Id: mcheck.c,v 1.22 1992/08/22 16:27:13 cpcahil Exp $";
  23. #endif
  24.  
  25. #define malloc_in_arena(ptr) (   ((DATATYPE*)(ptr) >= malloc_data_start) \
  26.                   && ((DATATYPE*)(ptr) <= malloc_data_end) )
  27.  
  28. /*
  29.  * Function:    malloc_check_str()
  30.  *
  31.  * Arguments:    func    - name of function calling this routine
  32.  *        str    - pointer to area to check
  33.  *
  34.  * Purpose:    to verify that if str is within the malloc arena, the data 
  35.  *        it points to does not extend beyond the applicable region.
  36.  *
  37.  * Returns:    Nothing of any use (function is void).
  38.  *
  39.  * Narrative:
  40.  *   IF pointer is within malloc arena
  41.  *      determin length of string
  42.  *      call malloc_verify() to verify data is withing applicable region
  43.  *   return 
  44.  *
  45.  * Mod History:    
  46.  *   90/01/24    cpcahil        Initial revision.
  47.  *   90/01/29    cpcahil        Added code to ignore recursive calls.
  48.  */
  49. VOIDTYPE
  50. malloc_check_str(func,file,line,str)
  51.     CONST char        * func;
  52.     CONST char        * file;
  53.     int              line;
  54.     CONST char        * str;
  55. {
  56.     static int          layers;
  57.     register CONST char    * s;
  58.  
  59.     MALLOC_INIT();
  60.  
  61.     /*
  62.      * if we are already in the malloc library somewhere, don't check
  63.      * things again.
  64.      */
  65.     if( in_malloc_code || (! (malloc_opts & MOPT_CKDATA) ) )
  66.     {
  67.         return;
  68.     }
  69.  
  70.     if( (layers++ == 0) &&  malloc_in_arena(str) )
  71.     {
  72.         for( s=str; *s; s++)
  73.         {
  74.         }
  75.         
  76.         malloc_verify(func,file,line,str,(SIZETYPE)(s-str+1));
  77.     }
  78.  
  79.     layers--;
  80. }
  81.  
  82. /*
  83.  * Function:    malloc_check_strn()
  84.  *
  85.  * Arguments:    func    - name of function calling this routine
  86.  *        str    - pointer to area to check
  87.  *         len     - max length of string
  88.  *
  89.  * Purpose:    to verify that if str is within the malloc arena, the data 
  90.  *        it points to does not extend beyond the applicable region.
  91.  *
  92.  * Returns:    Nothing of any use (function is void).
  93.  *
  94.  * Narrative:
  95.  *   IF pointer is within malloc arena
  96.  *      determin length of string
  97.  *      call malloc_verify() to verify data is withing applicable region
  98.  *   return 
  99.  *
  100.  * Mod History:    
  101.  *   90/01/24    cpcahil        Initial revision.
  102.  *   90/01/29    cpcahil        Added code to ignore recursive calls.
  103.  *   90/08/29    cpcahil        added length (for strn* functions)
  104.  */
  105. VOIDTYPE
  106. malloc_check_strn(func,file,line,str,len)
  107.     CONST char    * func;
  108.     CONST char     * file;
  109.     int          line;
  110.     CONST char    * str;
  111.     STRSIZE          len;
  112. {
  113.     register STRSIZE      i;
  114.     static int          layers;
  115.     register CONST char    * s;
  116.  
  117.     MALLOC_INIT();
  118.  
  119.     /*
  120.      * if we are already in the malloc library somewhere, don't check
  121.      * things again.
  122.      */
  123.     if( in_malloc_code || (! (malloc_opts & MOPT_CKDATA) ) )
  124.     {
  125.         return;
  126.     }
  127.  
  128.     if( (layers++ == 0) &&  malloc_in_arena(str) )
  129.     {
  130.         for( s=str,i=0; (i < len) && (*s != '\0'); i++,s++)
  131.         {
  132.         }
  133.  
  134.         /*
  135.          * if we found a null byte before len, add one to s so
  136.          * that we ensure that the null is counted in the bytes to
  137.          * check.
  138.          */
  139.         if( i < len )
  140.         {
  141.             s++;
  142.         }
  143.         malloc_verify(func,file,line,str,(SIZETYPE)(s-str));
  144.     }
  145.  
  146.     layers--;
  147. }
  148.  
  149. /*
  150.  * Function:    malloc_check_data()
  151.  *
  152.  * Arguments:    func    - name of function calling this routine
  153.  *        ptr    - pointer to area to check
  154.  *        len     - length to verify
  155.  *
  156.  * Purpose:    to verify that if ptr is within the malloc arena, the data 
  157.  *        it points to does not extend beyond the applicable region.
  158.  *
  159.  * Returns:    Nothing of any use (function is void).
  160.  *
  161.  * Narrative:
  162.  *   IF pointer is within malloc arena
  163.  *      call malloc_verify() to verify data is withing applicable region
  164.  *   return 
  165.  *
  166.  * Mod History:    
  167.  *   90/01/24    cpcahil        Initial revision.
  168.  *   90/01/29    cpcahil        Added code to ignore recursive calls.
  169.  */
  170. VOIDTYPE
  171. malloc_check_data(func,file,line,ptr,len)
  172.     CONST char    * func;
  173.     CONST char    * file;
  174.     int          line;
  175.     CONST DATATYPE    * ptr;
  176.     SIZETYPE      len;
  177. {
  178.     static int      layers;
  179.  
  180.     MALLOC_INIT();
  181.  
  182.     /*
  183.      * if we are already in the malloc library somewhere, don't check
  184.      * things again.
  185.      */
  186.     if( in_malloc_code || (! (malloc_opts & MOPT_CKDATA) ) )
  187.     {
  188.         return;
  189.     }
  190.  
  191.     if( layers++ == 0 )
  192.     {
  193.         DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...",
  194.             func,ptr,len);
  195.         if( malloc_in_arena(ptr) )
  196.         {
  197.             DEBUG0(10,"pointer in malloc arena, verifying...");
  198.             malloc_verify(func,file,line,ptr,len);
  199.         }
  200.     }
  201.  
  202.     layers--;
  203. }
  204.  
  205. /*
  206.  * Function:    malloc_verify()
  207.  *
  208.  * Arguments:    func    - name of function calling the malloc check routines
  209.  *        ptr    - pointer to area to check
  210.  *        len     - length to verify
  211.  *
  212.  * Purpose:    to verify that the data ptr points to does not extend beyond
  213.  *        the applicable malloc region.  This function is only called 
  214.  *        if it has been determined that ptr points into the malloc arena.
  215.  *
  216.  * Returns:    Nothing of any use (function is void).
  217.  *
  218.  * Narrative:
  219.  *
  220.  * Mod History:    
  221.  *   90/01/24    cpcahil        Initial revision.
  222.  */
  223. VOIDTYPE
  224. malloc_verify(func,file,line,ptr,len)
  225.     CONST char        * func;
  226.     CONST char        * file;
  227.     int              line;
  228.     register CONST DATATYPE    * ptr;
  229.     register SIZETYPE      len;
  230. {
  231.     register CONST struct mlist    * mptr = NULL;
  232.     
  233.     DEBUG5(40,"malloc_verify(%s, %s, %s, 0x%x,%d) called...",
  234.         func, file, line, ptr, len);
  235.  
  236.     /*
  237.      * since we know we have a pointer that is somewhere within the
  238.      * malloc region, let's take a guess that the current pointer is
  239.      * at the begining of a region and see if it has the correct values
  240.      */
  241.  
  242.     /*
  243.      * if we are on the correct boundry for a malloc data area pointer
  244.      */
  245.     if(   (((long)ptr) & malloc_round) == 0 )
  246.     {
  247.         mptr = (CONST struct mlist *)(((CONST char *) ptr ) - M_SIZE);
  248.  
  249.         if( ! GoodMlist(mptr) )
  250.         {
  251.             mptr = (CONST struct mlist *) NULL;
  252.         }
  253.     }
  254.  
  255.     /*
  256.      * if we haven't found it yet, let's try to look back just a few bytes
  257.      * to see if it is nearby
  258.      */
  259.     if( mptr == (struct mlist *) NULL)
  260.     {
  261.         register long    * lptr;
  262.         register int      i;
  263.  
  264.         lptr = (long *) (((long)ptr) & ~malloc_round);
  265.  
  266.         for(i=0; i < MAX_KLUDGE_CHECKS; i++)
  267.         {
  268.             lptr--;
  269.             if( ! malloc_in_arena(lptr) )
  270.             {
  271.                 mptr = (CONST struct mlist *) NULL;
  272.                 break;
  273.             }
  274.  
  275.             /*
  276.              * if we found the magic number
  277.               */
  278.             if( ((*lptr) & M_MAGIC_BITS) == M_MAGIC )
  279.             {
  280.                 mptr = (CONST struct mlist *)
  281.                     (((CONST char *)lptr) - M_FLAGOFF);
  282.  
  283.                 /*
  284.                  * if the pointer is good.
  285.                   */
  286.                 if( GoodMlist(mptr) )
  287.                 {
  288.                     break;
  289.                 }
  290.             }
  291.  
  292.         }
  293.  
  294.         /*
  295.          * if we didn't find an entry, make sure mptr is null
  296.          */
  297.         if( i == MAX_KLUDGE_CHECKS )
  298.         {
  299.             mptr = (CONST struct mlist *) NULL;
  300.         }
  301.     }
  302.  
  303.  
  304.     /*
  305.      * if we still haven't found the right segment, we have to do it the
  306.      * hard way and search along the malloc list
  307.      */
  308.     if( mptr == (CONST struct mlist *) NULL)
  309.     {
  310.         /*
  311.          * Find the malloc block that includes this pointer
  312.          */
  313.         mptr = &malloc_start;
  314.         while( mptr
  315.             && ! ((((CONST DATATYPE *)mptr) < (CONST DATATYPE *)ptr)
  316.             &&   (((DATATYPE *)(mptr->data+mptr->s.size)) > ptr) ) )
  317.         {
  318.             mptr = mptr->next;
  319.         }
  320.     }
  321.  
  322.     /*
  323.      * if ptr was not in a malloc block, it must be part of
  324.      *    some direct sbrk() stuff, so just return.
  325.      */
  326.     if( ! mptr )
  327.     {
  328.         DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr);
  329.         return;
  330.     }
  331.     
  332.     /*
  333.       * Now we have a valid malloc block that contains the indicated
  334.      * pointer.  We must verify that it is withing the requested block
  335.      * size (as opposed to the real block size which is rounded up to
  336.      * allow for correct alignment).
  337.      */
  338.  
  339.     DEBUG4(60,"Checking  0x%x-0x%x, 0x%x-0x%x",
  340.             ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
  341.     
  342.     if(    (ptr < (DATATYPE *)mptr->data)
  343.           || ((((CONST char *)ptr)+len) > (char *)(mptr->data+mptr->r_size)) )
  344.     {
  345.         DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x",
  346.             ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
  347.  
  348.         malloc_errno = M_CODE_OUTOF_BOUNDS;
  349.         malloc_warning(func,file,line,mptr);
  350.     }
  351.     else if ( (mptr->flag&M_INUSE) == 0 )
  352.     {
  353.         DEBUG4(0,"segment not in use 0x%x-0x%x, 0x%x-0x%x",
  354.             ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
  355.  
  356.         malloc_errno = M_CODE_NOT_INUSE;
  357.         malloc_warning(func,file,line,mptr);
  358.     }
  359.  
  360.     return;
  361. }
  362.  
  363. /*
  364.  * GoodMlist() - return true if mptr appears to point to a valid segment
  365.  */
  366. int
  367. GoodMlist(mptr)
  368.     register CONST struct mlist * mptr;
  369. {
  370.  
  371.     /*
  372.      * return true if
  373.      *     1. the segment has a valid magic number
  374.      *     2. the inuse flag is set
  375.      *    3. the previous linkage is set correctly
  376.      *    4. the next linkage is set correctly
  377.      *    5. either next and prev is not null
  378.      */
  379.         
  380.     return(    ((mptr->flag&M_MAGIC_BITS) == M_MAGIC)
  381.         && ((mptr->flag&M_INUSE) != 0 )
  382.          && (mptr->prev ?
  383.             (malloc_in_arena(mptr->prev) && (mptr->prev->next == mptr)) : 1 )
  384.          && (mptr->next ?
  385.             (malloc_in_arena(mptr->next) && (mptr->next->prev == mptr)) : 1 )
  386.             && ((mptr->next == NULL) || (mptr->prev == NULL)) );
  387.  
  388. } /* GoodMlist(... */
  389. /*
  390.  * $Log: mcheck.c,v $
  391.  * Revision 1.22  1992/08/22  16:27:13  cpcahil
  392.  * final changes for pl14
  393.  *
  394.  * Revision 1.21  1992/06/27  22:48:48  cpcahil
  395.  * misc fixes per bug reports from first week of reviews
  396.  *
  397.  * Revision 1.20  1992/06/22  23:40:10  cpcahil
  398.  * many fixes for working on small int systems
  399.  *
  400.  * Revision 1.19  1992/05/09  00:16:16  cpcahil
  401.  * port to hpux and lots of fixes
  402.  *
  403.  * Revision 1.18  1992/05/08  02:30:35  cpcahil
  404.  * minor cleanups from minix/atari port
  405.  *
  406.  * Revision 1.17  1992/05/08  01:44:11  cpcahil
  407.  * more performance enhancements
  408.  *
  409.  * Revision 1.16  1992/05/06  04:53:29  cpcahil
  410.  * performance enhancments
  411.  *
  412.  * Revision 1.15  1992/04/13  03:06:33  cpcahil
  413.  * Added Stack support, marking of non-leaks, auto-config, auto-testing
  414.  *
  415.  * Revision 1.14  1992/03/01  12:42:38  cpcahil
  416.  * added support for managing freed areas and fixed doublword bndr problems
  417.  *
  418.  * Revision 1.13  1992/01/30  12:23:06  cpcahil
  419.  * renamed mallocint.h -> mallocin.h
  420.  *
  421.  * Revision 1.12  1992/01/10  17:51:03  cpcahil
  422.  * more void stuff that slipped by
  423.  *
  424.  * Revision 1.11  1992/01/10  17:28:03  cpcahil
  425.  * Added support for overriding void datatype
  426.  *
  427.  * Revision 1.10  1991/12/31  02:23:29  cpcahil
  428.  * fixed verify bug of strncpy when len was exactly same as strlen
  429.  *
  430.  * Revision 1.9  91/12/02  19:10:12  cpcahil
  431.  * changes for patch release 5
  432.  * 
  433.  * Revision 1.8  91/11/25  14:42:01  cpcahil
  434.  * Final changes in preparation for patch 4 release
  435.  * 
  436.  * Revision 1.7  91/11/24  00:49:29  cpcahil
  437.  * first cut at patch 4
  438.  * 
  439.  * Revision 1.6  91/11/20  11:54:11  cpcahil
  440.  * interim checkin
  441.  * 
  442.  * Revision 1.5  90/08/29  22:23:48  cpcahil
  443.  * added new function to check on strings up to a specified length 
  444.  * and used it within several strn* functions.
  445.  * 
  446.  * Revision 1.4  90/05/11  00:13:09  cpcahil
  447.  * added copyright statment
  448.  * 
  449.  * Revision 1.3  90/02/24  21:50:22  cpcahil
  450.  * lots of lint fixes
  451.  * 
  452.  * Revision 1.2  90/02/24  17:29:38  cpcahil
  453.  * changed $Header to $Id so full path wouldnt be included as part of rcs 
  454.  * id string
  455.  * 
  456.  * Revision 1.1  90/02/24  14:57:03  cpcahil
  457.  * Initial revision
  458.  * 
  459.  */
  460.