/* fortify.h - V2.2 - All C & C++ source files to be fortified should #include this file */

/*
 *     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
 */

#ifndef __FORTIFY_H__
#define __FORTIFY_H__

#include <stdlib.h>
#include <string.h>

/* the user's options */
#include "ufortify.h"

/* Ensure the configuration parameters have sensible defaults */
#ifndef FORTIFY_STORAGE
#define FORTIFY_STORAGE
#endif

#ifndef FORTIFY_ALIGNMENT
#define FORTIFY_ALIGNMENT                    sizeof(double)
#endif

#ifndef FORTIFY_BEFORE_SIZE
#define FORTIFY_BEFORE_SIZE                  32
#endif
#ifndef FORTIFY_BEFORE_VALUE
#define FORTIFY_BEFORE_VALUE                 0xA3
#endif

#ifndef FORTIFY_AFTER_SIZE
#define FORTIFY_AFTER_SIZE                   32
#endif

#ifndef FORTIFY_AFTER_VALUE
#define FORTIFY_AFTER_VALUE                  0xA5
#endif

#ifndef FORTIFY_FILL_ON_ALLOCATE_VALUE
#define FORTIFY_FILL_ON_ALLOCATE_VALUE       0xA7
#endif

#ifndef FORTIFY_FILL_ON_DEALLOCATE_VALUE
#define FORTIFY_FILL_ON_DEALLOCATE_VALUE     0xA9
#endif

#ifndef FORTIFY_LOCK
#define FORTIFY_LOCK()
#endif

#ifndef FORTIFY_UNLOCK
#define FORTIFY_UNLOCK()
#endif

#ifndef FORTIFY_CHECKSUM_VALUE
#define FORTIFY_CHECKSUM_VALUE               0x0AD0
#endif

#ifndef FORTIFY_DELETE_STACK_SIZE
#define FORTIFY_DELETE_STACK_SIZE    256
#endif

#ifndef FORTIFY_NEW_HANDLER_FUNC
typedef void (*Fortify_NewHandlerFunc) (void);
#define FORTIFY_NEW_HANDLER_FUNC Fortify_NewHandlerFunc
#endif

/*
 * Code to detect and configure for various compilers lives here.
 */

#ifdef __GNUG__
    /* GCC configuration */
#define FORTIFY_PROVIDE_ARRAY_NEW
#define FORTIFY_PROVIDE_ARRAY_DELETE
#endif

#ifdef __BC45__
    /* Borland C++ 4.5 configuration */
#define FORTIFY_PROVIDE_ARRAY_NEW
#define FORTIFY_PROVIDE_ARRAY_DELETE
#define FORTIFY_FAIL_ON_ZERO_MALLOC
#endif

#ifdef __SASC
	/* SAS configuration */
#define FORTIFY_FAIL_ON_ZERO_MALLOC
#endif

/* Allocators */
#define Fortify_Allocator_malloc            0	/* ANSI C   */
#define Fortify_Allocator_calloc            1	/* ANSI C   */
#define Fortify_Allocator_realloc           2	/* ANSI C   */
#define Fortify_Allocator_strdup            3	/*      C   */
#define Fortify_Allocator_new               4	/* ANSI C++ */
#define Fortify_Allocator_array_new         5	/* Some C++ */

/* Deallocators */
#define Fortify_Deallocator_nobody          0
#define Fortify_Deallocator_free            1	/* ANSI C   */
#define Fortify_Deallocator_realloc         2	/* ANSI C   */
#define Fortify_Deallocator_delete          3	/* ANSI C++ */
#define Fortify_Deallocator_array_delete    4	/* Some C++ */

/* Public Fortify Types */
typedef void (*Fortify_OutputFuncPtr) (const char *);

#ifdef __cplusplus
extern "C"
{
#endif

/* Core Fortify Functions */
  void *Fortify_Allocate (size_t size, unsigned char allocator,
			  const char *file, unsigned long line);
  void Fortify_Deallocate (void *uptr, unsigned char deallocator,
			   const char *file, unsigned long line);
  unsigned long Fortify_CheckAllMemory (const char *file, unsigned long line);
  unsigned long Fortify_ListAllMemory (const char *file, unsigned long line);
  unsigned long Fortify_DumpAllMemory (const char *file, unsigned long line);
  int Fortify_CheckPointer (void *uptr, const char *file, unsigned long line);
  void Fortify_LabelPointer (void *uptr, const char *label, const char *file,
			     unsigned long line);
  unsigned char Fortify_EnterScope (const char *file, unsigned long line);
  unsigned char Fortify_LeaveScope (const char *file, unsigned long line);
  int Fortify_ErrorsDetected (void);
  void Fortify_OutputStatistics (const char *file, unsigned long line);
  unsigned long Fortify_GetCurrentAllocation (const char *file,
					      unsigned long line);
  void Fortify_SetAllocationLimit (unsigned long Limit, const char *file,
				   unsigned long line);
  int Fortify_SetFailRate (int Percent);
  Fortify_OutputFuncPtr Fortify_SetOutputFunc (Fortify_OutputFuncPtr Output);
  void Fortify_Disable (const char *file, unsigned long line);

/* Fortify versions of the ANSI C memory allocation functions */
  void *Fortify_malloc (size_t size, const char *file, unsigned long line);
  void *Fortify_realloc (void *ptr, size_t new_size, const char *file,
			 unsigned long line);
  void *Fortify_calloc (size_t num, size_t size, const char *file,
			unsigned long line);
  void Fortify_free (void *uptr, const char *file, unsigned long line);

/* Fortify versions of some non-ANSI C memory allocation functions */
#ifdef FORTIFY_STRDUP
  char *Fortify_strdup (const char *oldStr, const char *file,
			unsigned long line);
#endif

#ifdef __cplusplus
/* Magic global variable */
  extern int gbl_FortifyMagic;
#endif

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
#include <new.h>

    /* Fortify versions of new and delete */
void *operator new (size_t size);
void *operator new (size_t size, const char *file, unsigned long line);
void operator delete (void *pointer);
void Fortify_PreDelete (const char *file, unsigned long line);
void Fortify_PostDelete ();

    /* Some compilers use a different new operator for newing arrays.
     * This includes GNU G++ (2.6.0) and Borland C++ (4.02)
     */
#ifdef FORTIFY_PROVIDE_ARRAY_NEW
void *operator new[] (size_t size);
void *operator new[] (size_t size, const char *file, unsigned long line);
#endif

    /* Some compilers provide a different delete operator for deleting arrays.
     * This incldues GNU G++ (2.6.0)
     */
#ifdef FORTIFY_PROVIDE_ARRAY_DELETE
void operator delete[] (void *pointer);
#endif

#endif /* __cplusplus */

#ifndef __FORTIFY_C__		/* Only define the macros if we're NOT in fortify.c */

/* Add file and line information to the fortify calls */
#ifdef FORTIFY
    /* Core Fortify Functions */
#define Fortify_CheckAllMemory()       Fortify_CheckAllMemory(__FILE__, __LINE__)
#define Fortify_ListAllMemory()        Fortify_ListAllMemory (__FILE__, __LINE__)
#define Fortify_DumpAllMemory()        Fortify_DumpAllMemory (__FILE__, __LINE__)
#define Fortify_CheckPointer(ptr)      Fortify_CheckPointer(ptr, __FILE__, __LINE__)
#define Fortify_LabelPointer(ptr,str)  Fortify_LabelPointer(ptr, str, __FILE__, __LINE__)
#define Fortify_EnterScope()           Fortify_EnterScope(__FILE__, __LINE__)
#define Fortify_LeaveScope()           Fortify_LeaveScope(__FILE__, __LINE__)
#define Fortify_OutputStatistics()     Fortify_OutputStatistics(__FILE__, __LINE__)
#define Fortify_GetCurrentAllocation() Fortify_GetCurrentAllocation(__FILE__, __LINE__)
#define Fortify_SetAllocationLimit(x)  Fortify_SetAllocationLimit(x, __FILE__, __LINE__)
#define Fortify_Disable()              Fortify_Disable(__FILE__, __LINE__)

    /* Fortify versions of the ANSI C memory allocation functions */
#define malloc(size)                   Fortify_malloc(size, __FILE__, __LINE__)
#define realloc(ptr,new_size)          Fortify_realloc(ptr, new_size, __FILE__, __LINE__)
#define calloc(num,size)               Fortify_calloc(num, size, __FILE__, __LINE__)
#define free(ptr)                      Fortify_free(ptr, __FILE__, __LINE__)

    /* Fortify versions of some non-ANSI C memory allocation functions */
#ifdef FORTIFY_STRDUP
#define strdup(ptr)                Fortify_strdup(ptr, __FILE__, __LINE__)
#endif

    /* Fortify versions of new and delete */
#ifdef __cplusplus
#define Fortify_New                new(__FILE__, __LINE__)
#define Fortify_Delete             for(gbl_FortifyMagic = 1, \
                                               Fortify_PreDelete(__FILE__, __LINE__); \
                                               gbl_FortifyMagic; Fortify_PostDelete()) \
                                                       gbl_FortifyMagic = 0, delete
#define new                        Fortify_New
#define delete                     Fortify_Delete
#endif /* __cplusplus */

#else /* Define the special fortify functions away to nothing */

#define Fortify_CheckAllMemory()       0
#define Fortify_ListAllMemory()        0
#define Fortify_DumpAllMemory()        0
#define Fortify_CheckPointer(ptr)      1
#define Fortify_LabelPointer(ptr,str)
#define Fortify_SetOutputFunc()        0
#define Fortify_SetMallocFailRate(p)   0
#define Fortify_EnterScope()           0
#define Fortify_LeaveScope()           0
#define Fortify_OutputStatistics()     0
#define Fortify_GetCurrentAllocation() 0
#define Fortify_SetAllocationLimit(x)  0
#define Fortify_Disable()              0

#ifdef __cplusplus
#define Fortify_New                    new
#define Fortify_Delete                 delete
#endif /* __cplusplus */

#endif /*   FORTIFY     */
#endif /* __FORTIFY_C__ */
#endif /* __FORTIFY_H__ */
