⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fortify.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* fortify.cxx - A fortified memory allocation shell - V2.2 */

/*
 * This software is not public domain. All material in
 * this archive is (C) Copyright 1995 Simon P. Bullen. The
 * software is freely distributable, with the condition that
 * no more than a nominal fee is charged for media.
 * Everything in this distribution must be kept together, in
 * original, unmodified form.
 *
 * The software may be modified for your own personal use,
 * but modified files may not be distributed.
 *
 * The material is provided "as is" without warranty of
 * any kind. The author accepts no responsibility for damage
 * caused by this software.
 *
 * This software may not be used in any way by Microsoft
 * Corporation or its subsidiaries, or current employees of
 * Microsoft Corporation or its subsidiaries.
 *
 * This software may not be used for the construction,
 * development, production, or testing of weapon systems of
 * any kind.
 *
 * This software may not be used for the construction,
 * development, production, or use of plants/installations
 * which include the processing of radioactive/fissionable
 * material.
 */

/*
 * If you use this software at all, I'd love to hear from
 * you.  All questions, criticisms, suggestions, praise and
 * postcards are most welcome.
 * 
 *            email:    sbullen@cybergraphic.com.au
 * 
 *            snail:    Simon P. Bullen
 *                      PO BOX 12138
 *                      A'Beckett St.
 *                      Melbourne 3000
 *                      Australia
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <ctype.h>
#include <time.h>

/* Prototypes and such */
#define __FORTIFY_C__

#include "wattcp.h"
#include "misc.h"

#if (DOSX)  /* Using inchksum_fast() function */
  #undef  FORTIFY_CHECKSUM_VALUE
  #define FORTIFY_CHECKSUM_VALUE 0xFFFF
#endif

#include "fortify.h"
#include "chksum.h"

#if defined(USE_FORTIFY) || defined(USE_BSD_FORTIFY)


#define STATIC

/*
 * struct Header - this structure is used 
 * internally by Fortify to manage it's 
 * own private lists of memory.
 */
struct Header {
       WORD           Checksum;     /* For the integrity of our goodies  */
       const char    *File;         /* The sourcefile of the allocator   */
       DWORD          Line;         /* The sourceline of the allocator   */
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
       const char    *FreedFile;    /* The sourcefile of the deallocator */
       DWORD          FreedLine;    /* The sourceline of the deallocator */
       BYTE           Deallocator;  /* The deallocator used              */
#endif
       size_t         Size;         /* The size of the malloc'd block    */
       struct Header *Prev;         /* Previous link                     */
       struct Header *Next;         /* Next link                         */
       char          *Label;        /* User's Label (may be null)        */
       BYTE           Scope;        /* Scope level of the caller         */
       BYTE           Allocator;    /* malloc/realloc/new/etc            */
     };

/*
 * Round x up to the nearest multiple of n.
 */
#define ROUND_UP(x,n)        ((((x) + (n)-1)/(n))*(n))

#define FORTIFY_HEADER_SIZE  ROUND_UP(sizeof(struct Header), sizeof(WORD))

/*
 * FORTIFY_ALIGNED_BEFORE_SIZE is FORTIFY_BEFORE_SIZE rounded up to the
 * next multiple of FORTIFY_ALIGNMENT. This is so that we can guarantee
 * the alignment of user memory for such systems where this is important
 * (eg storing doubles on a SPARC)
 */
#define FORTIFY_ALIGNED_BEFORE_SIZE ( \
        ROUND_UP (FORTIFY_HEADER_SIZE+FORTIFY_BEFORE_SIZE, FORTIFY_ALIGNMENT) \
        - FORTIFY_HEADER_SIZE)

/*
 * FORTIFY_OVERHEAD is the total overhead added by Fortify to each
 * memory block.
 */
#define FORTIFY_OVERHEAD (FORTIFY_HEADER_SIZE         + \
                          FORTIFY_ALIGNED_BEFORE_SIZE + \
                          FORTIFY_AFTER_SIZE)


/*
 * Static Function Prototypes
 */
STATIC int  st_CheckBlock         (struct Header *h, const char *file, DWORD line);
STATIC int  st_CheckFortification (BYTE *ptr, BYTE value, size_t size);
STATIC void st_SetFortification   (BYTE *ptr, BYTE value, size_t size);
STATIC void st_OutputFortification(BYTE *ptr, BYTE value, size_t size);
STATIC void st_HexDump            (BYTE *ptr, size_t offset, size_t size, int title);
STATIC int  st_IsHeaderValid      (struct Header *h);
STATIC void st_MakeHeaderValid    (struct Header *h);
STATIC WORD st_ChecksumHeader     (struct Header *h);
STATIC int  st_IsOnAllocatedList  (struct Header *h);
STATIC void st_OutputHeader       (struct Header *h);
STATIC void st_OutputMemory       (struct Header *h);
STATIC void st_OutputLastVerifiedPoint(void);
STATIC void st_DefaultOutput      (const char *String);
STATIC const char *st_MemoryBlockString(struct Header *h);
STATIC void st_OutputDeleteTrace (void);

#if defined (FORTIFY_TRACK_DEALLOCATED_MEMORY)
#if defined (FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY) && \
    defined (FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY)
    STATIC const char *st_DeallocatedMemoryBlockString(struct Header *h);
#endif
    STATIC int st_IsOnDeallocatedList(struct Header *h);
    STATIC int st_PurgeDeallocatedBlocks(DWORD Bytes, const char *file, DWORD line);
    STATIC int st_PurgeDeallocatedScope(BYTE Scope, const char *file, DWORD line);
    STATIC int st_CheckDeallocatedBlock(struct Header *h, const char *file, DWORD line);
    STATIC void st_FreeDeallocatedBlock(struct Header *h, const char *file, DWORD line);
#endif


/*
 * Static variables
 */
STATIC char                  st_Buffer[4096]     = { 0 }; /* don't use BSS */
STATIC struct Header        *st_AllocatedHead    = 0;
STATIC int                   st_AllocateFailRate = 0;
STATIC Fortify_OutputFuncPtr st_Output           = st_DefaultOutput;
STATIC const char           *st_LastVerifiedFile = "unknown";
STATIC DWORD                 st_LastVerifiedLine = 0;
STATIC BYTE                  st_Scope            = 0;
STATIC BYTE                  st_Disabled         = 0;

#if defined(__HIGHC__) && 0 // !! not yet
STATIC char st_LockDataStart = 0;
#endif

#ifdef __cplusplus
  int    gbl_FortifyMagic = 0;
  STATIC const char *st_DeleteFile[FORTIFY_DELETE_STACK_SIZE];
  STATIC DWORD       st_DeleteLine[FORTIFY_DELETE_STACK_SIZE];
  STATIC DWORD       st_DeleteStackTop;
#endif

/* statistics */
STATIC DWORD  st_MaxBlocks        = 0;
STATIC DWORD  st_MaxAllocation    = 0;
STATIC DWORD  st_CurBlocks        = 0;
STATIC DWORD  st_CurAllocation    = 0;
STATIC DWORD  st_Allocations      = 0;
STATIC DWORD  st_Frees            = 0;
STATIC DWORD  st_TotalAllocation  = 0;
STATIC DWORD  st_AllocationLimit  = 0xffffffff;

#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
  STATIC struct Header *st_DeallocatedHead  = 0;
  STATIC struct Header *st_DeallocatedTail  = 0;
  STATIC DWORD          st_TotalDeallocated = 0;
#endif

 
/* allocators */
STATIC const char *st_AllocatorName[] = {
                  "malloc()",
                  "calloc()",
                  "realloc()",
                  "strdup()",
                  "new",
                  "new[]"
                };

/* deallocators */
STATIC const char *st_DeallocatorName[] = {
                  "nobody",
                  "free()",
                  "realloc()",
                  "delete",
                  "delete[]"
                };

STATIC const BYTE st_ValidDeallocator[] = {
    (1 << Fortify_Deallocator_free) | (1 << Fortify_Deallocator_realloc),
    (1 << Fortify_Deallocator_free) | (1 << Fortify_Deallocator_realloc),
    (1 << Fortify_Deallocator_free) | (1 << Fortify_Deallocator_realloc),
    (1 << Fortify_Deallocator_free) | (1 << Fortify_Deallocator_realloc),
#if defined(FORTIFY_PROVIDE_ARRAY_NEW) && defined(FORTIFY_PROVIDE_ARRAY_DELETE)
    (1 << Fortify_Deallocator_delete),
    (1 << Fortify_Deallocator_array_delete)
#else
    (1 << Fortify_Deallocator_delete) | (1 << Fortify_Deallocator_array_delete),
    (1 << Fortify_Deallocator_delete) | (1 << Fortify_Deallocator_array_delete)
#endif
};

STATIC char st_LockDataFill[4096] = { 0 };
STATIC char st_LockDataEnd        = 0;


#if defined(__HIGHC__) && 0 // !! not yet

#include <pharlap.h>
#include <hw386.h>

/*
 *  Change page-attributes for local data.
 *  Set to present or non-present pages.
 */
STATIC Fortify_LockLocalData (int lock)
{
  UINT  lockSize  = (ULONG)&st_LockDataEnd - (ULONG)&st_LockDataStart;
  ULONG num_pages = (lockSize + 4095) / 4096;
  ULONG page      = ((ULONG)&st_LockDataStart + 4095) / 4096;

  for ( ; page < page + num_pages; page++)
  {
    ULONG pte, ptInfo;
    if (_dx_rd_ptinfl (page << 12, &pte, &ptInfo))
       break;
    if (lock)
         pte &= ~PE_PRESENT;
    else pte |=  PE_PRESENT;
    if (_dx_wr_ptinfl (page << 12, pte, ptInfo))
       break;
  }
}
#endif


/*
 * Fortify_Allocate() - allocate a block of fortified memory
 */
void *FORTIFY_STORAGE
Fortify_Allocate (size_t size, BYTE allocator, const char *file, DWORD line)
{
  struct Header *h;
  int    another_try;
  BYTE  *ptr = NULL;

  /*
   * If Fortify has been disabled, then it's easy
   */
  if (st_Disabled)
  {
#ifdef FORTIFY_FAIL_ON_ZERO_MALLOC
    if (size == 0 &&
        (allocator == Fortify_Allocator_new ||
         allocator == Fortify_Allocator_array_new))
    {
      /*
       * A new of zero bytes must succeed, but a malloc of
       * zero bytes probably won't
       */
      return malloc(1);
    }
#endif

    return malloc(size);
  }

#ifdef FORTIFY_CHECK_ALL_MEMORY_ON_ALLOCATE
  Fortify_CheckAllMemory (file, line);
#endif  

  if (st_AllocateFailRate > 0)
  {
    if (rand() % 100 < st_AllocateFailRate)
    {
#ifdef FORTIFY_WARN_ON_FALSE_FAIL
      sprintf (st_Buffer,
               "\nFortify: A \"%s\" of %lu bytes \"false failed\" at %s.%lu\n",
               st_AllocatorName[allocator], (DWORD)size, file, line);
      st_Output (st_Buffer);
#endif
      return (0);
    }
  }

  /* Check to see if this allocation will
   * push us over the artificial limit
   */
  if (st_CurAllocation + size > st_AllocationLimit)
  {
#ifdef FORTIFY_WARN_ON_FALSE_FAIL
    sprintf (st_Buffer,
             "\nFortify: A \"%s\" of %lu bytes \"false failed\" at %s.%lu\n",
             st_AllocatorName[allocator], (DWORD)size, file, line);
    st_Output (st_Buffer);
#endif
    return (0);
  }

#ifdef FORTIFY_WARN_ON_ZERO_MALLOC
  if (size == 0 && (allocator == Fortify_Allocator_malloc ||
                    allocator == Fortify_Allocator_calloc ||
                    allocator == Fortify_Allocator_realloc))
  {
    sprintf(st_Buffer,
            "\nFortify: A \"%s\" of 0 bytes attempted at %s.%lu\n",
            st_AllocatorName[allocator], file, line);
    st_Output(st_Buffer);
  }
#endif /* FORTIFY_WARN_ON_ZERO_MALLOC */

#ifdef FORTIFY_FAIL_ON_ZERO_MALLOC
  if (size == 0 && (allocator == Fortify_Allocator_malloc ||
                    allocator == Fortify_Allocator_calloc ||
                    allocator == Fortify_Allocator_realloc))
  {
#ifdef FORTIFY_WARN_ON_ALLOCATE_FAIL
    sprintf(st_Buffer, "\nFortify: A \"%s\" of %lu bytes failed at %s.%lu\n",
            st_AllocatorName[allocator], (DWORD)size, file, line);
    st_Output(st_Buffer);
#endif /* FORTIFY_WARN_ON_ALLOCATE_FAIL */
    return (0);
  }
#endif /* FORTIFY_FAIL_ON_ZERO_MALLOC */    

#ifdef FORTIFY_WARN_ON_SIZE_T_OVERFLOW
    /*
     * Ensure the size of the memory block
     * plus the overhead isn't bigger than
     * size_t (that'd be a drag)
     */
    {
        size_t private_size = FORTIFY_HEADER_SIZE
                            + FORTIFY_ALIGNED_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE;

        if (private_size < size)
        {
            sprintf(st_Buffer, 
                    "\nFortify: A \"%s\" of %lu bytes has overflowed size_t at %s.%lu\n",
                    st_AllocatorName[allocator], (DWORD)size, file, line);
            st_Output(st_Buffer);
            return (0);
        }
#if (DOSX) && defined(__WATCOMC__) && 0
        if (private_size >= 65536UL)
        {
            sprintf(st_Buffer, 
                    "\nFortify: A \"%s\" of %lu bytes has exceeded 64kB limit by %d bytes, at %s.%lu\n",
                    st_AllocatorName[allocator], (DWORD)size,
                    private_size - size, file, line);
            st_Output(st_Buffer);
            return (0);
        }
#endif
    }
#endif                              

    another_try = 1;
    do
    {
        /*
         * malloc the memory, including the space 
         * for the header and fortification buffers
         */  
        ptr = (BYTE *)malloc ( FORTIFY_HEADER_SIZE
                                   + FORTIFY_ALIGNED_BEFORE_SIZE
                                   + size
                                   + FORTIFY_AFTER_SIZE);

#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
        /*
         * If we're tracking deallocated memory, then
         * we can free some of it, rather than let
         * this malloc fail
         */
        if (!ptr)
           another_try = st_PurgeDeallocatedBlocks(size, file, line);

#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */

    }
    while (!ptr && another_try);

    if (!ptr)
    {
#ifdef FORTIFY_WARN_ON_ALLOCATE_FAIL
        sprintf(st_Buffer, "\nFortify: A \"%s\" of %lu bytes failed at %s.%lu\n",
                st_AllocatorName[allocator], (DWORD)size, file, line);
        st_Output(st_Buffer);
#endif
        return (0);
    }

    /*
     * Begin Critical Region
     */
    FORTIFY_LOCK();


    /* 
     * Make the head's prev pointer point to us
     * ('cos we're about to become the head)
     */
    if (st_AllocatedHead)
    {
        st_CheckBlock(st_AllocatedHead, file, line);
        /* what should we do if this fails? (apart from panic) */

        st_AllocatedHead->Prev = (struct Header *)ptr;
        st_MakeHeaderValid(st_AllocatedHead);  
    }

    /*
     * Initialize and validate the header
     */
    h = (struct Header *)ptr;
    h->Size      = size;
    h->File      = file;
    h->Line      = line;  
    h->Next      = st_AllocatedHead;
    h->Prev      = 0;
    h->Scope     = st_Scope;
    h->Allocator = allocator;
    h->Label     = 0;
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
    h->FreedFile = 0;
    h->FreedLine = 0;
    h->Deallocator = Fortify_Deallocator_nobody;
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
    st_MakeHeaderValid(h);
    st_AllocatedHead = h;
  
    /*
     * Initialize the fortifications
     */    
    st_SetFortification(ptr + FORTIFY_HEADER_SIZE,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -