You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2352 lines
61 KiB
2352 lines
61 KiB
/*
|
|
* FILE:
|
|
* fortify.c
|
|
*
|
|
* DESCRIPTION:
|
|
* A fortified shell for malloc, realloc, calloc, strdup, getcwd, tempnam
|
|
* and free.
|
|
* To use Fortify, each source file will need to #include "fortify.h". To
|
|
* enable Fortify, define the symbol FORTIFY. If FORTIFY is not defined, it
|
|
* will compile away to nothing. If you do not have stderr available, you may
|
|
* wish to set an alternate output function. See _Fortify_SetOutputFunc(),
|
|
* below.
|
|
* You will also need to link in fortify.o
|
|
*
|
|
* None of the functions in this file should really be called
|
|
* directly; they really should be called through the macros
|
|
* defined in fortify.h
|
|
*
|
|
*/
|
|
|
|
#if defined FORTIFY
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <stdlib.h>
|
|
|
|
#if defined MSDOS || defined __BORLANDC__ || defined WIN32 || defined __HIGHC__
|
|
# include <direct.h>
|
|
#endif
|
|
|
|
extern int EndOfPgr(int);
|
|
|
|
#define __FORTIFY_C__ /* So fortify.h knows to not define the fortify macros */
|
|
#include "fortify.h"
|
|
|
|
#include "ufortify.h" /* the user's options */
|
|
|
|
char *_Fortify_file=NULL;
|
|
int _Fortify_line=0;
|
|
|
|
#ifndef FORTIFY_TRANSPARENT
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
|
|
#if defined MSDOS || defined __BORLANDC__ || defined WIN32 || defined __HIGHC__
|
|
# if !defined WIN32
|
|
# undef MSDOS
|
|
# define MSDOS
|
|
# endif
|
|
# include <conio.h>
|
|
#else
|
|
# include <unistd.h>
|
|
# include <termio.h>
|
|
# define getch() getchar()
|
|
#endif
|
|
|
|
#if defined _WINDOWS
|
|
# include "windows.h"
|
|
# if !defined WIN32
|
|
# include "toolhelp.h"
|
|
# endif
|
|
#endif
|
|
|
|
#if defined LONGNAME
|
|
# include "longname.h"
|
|
#endif
|
|
|
|
#if !defined MIN
|
|
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#endif
|
|
|
|
struct Header
|
|
{
|
|
char *File; /* The sourcefile of the caller */
|
|
unsigned short Line; /* The sourceline of the caller */
|
|
size_t Size; /* The size of the malloc'd block */
|
|
struct Header *Prev, /* List pointers */
|
|
*Next;
|
|
int Checksum; /* For validating the Header structure; see ChecksumHeader() */
|
|
unsigned char Scope;
|
|
};
|
|
|
|
#if defined AViiON || defined __GNUC__ || defined _MSC_VER
|
|
# define _static static
|
|
#else
|
|
# define _static
|
|
#endif
|
|
|
|
_static char *address __OF((void *addr));
|
|
_static int TimeToCheck __OF((void));
|
|
_static int CheckBlock __OF((struct Header *h, char *file, unsigned long line));
|
|
_static int CheckPointer __OF((unsigned char *ptr, unsigned long size, char *file, unsigned long line));
|
|
_static int CheckFortification __OF((unsigned char *ptr, unsigned char value, size_t size));
|
|
_static void SetFortification __OF((unsigned char *ptr, unsigned char value, size_t size));
|
|
_static void OutputFortification __OF((unsigned char *ptr, unsigned char value, size_t size));
|
|
_static int IsHeaderValid __OF((struct Header *h));
|
|
_static void MakeHeaderValid __OF((struct Header *h));
|
|
_static int ChecksumHeader __OF((struct Header *h));
|
|
_static int IsOnList __OF((struct Header *h));
|
|
_static void OutputHeader __OF((struct Header *h));
|
|
_static void OutputMemory __OF((struct Header *h));
|
|
_static void st_DefaultOutput __OF((char *String));
|
|
_static void WaitIfstdOutput __OF((void));
|
|
|
|
static char stdOutput = 0; /* If true, did some stderr output */
|
|
static OutputFuncPtr st_Output = st_DefaultOutput; /* Output function for errors */
|
|
|
|
#if !defined MSDOS && !defined WIN32
|
|
static int strnicmp(s1,s2,maxlen)
|
|
char *s1,*s2;
|
|
size_t maxlen;
|
|
{
|
|
while ((maxlen) && (*s1) && (*s2) && (toupper(*s1)==toupper(*s2))) {
|
|
maxlen--;
|
|
s1++;
|
|
s2++;
|
|
}
|
|
return((maxlen) ? toupper(*s1)-toupper(*s2) : 0);
|
|
}
|
|
|
|
static int stricmp(s1,s2)
|
|
char *s1,*s2;
|
|
{
|
|
return(strnicmp(s1,s2,strlen(s1)+1));
|
|
}
|
|
#endif
|
|
|
|
static char *address(void *addr)
|
|
{
|
|
static char str[80];
|
|
|
|
#if defined KNOWS_POINTER_TYPE
|
|
sprintf(str,"%p",addr);
|
|
#else
|
|
sprintf(str,"%lx",(unsigned long) addr);
|
|
#endif
|
|
return(str);
|
|
}
|
|
|
|
#ifdef FORTIFY_CheckInterval
|
|
int TimeToCheck()
|
|
{
|
|
static time_t lastcheck=0L;
|
|
time_t t;
|
|
int ret = 0;
|
|
|
|
time(&t);
|
|
if ((lastcheck==0L) || (t-lastcheck>=FORTIFY_CheckInterval))
|
|
{
|
|
lastcheck = t;
|
|
ret = 1;
|
|
}
|
|
return(ret);
|
|
}
|
|
#endif
|
|
|
|
static FILE *gfile=NULL;
|
|
static int Nchars=0,Nlines=0;
|
|
static char flag=0;
|
|
|
|
static void _Fortify_NoOutput()
|
|
{
|
|
}
|
|
|
|
static void st_DefaultOutput(char *String)
|
|
{
|
|
static FILE *file;
|
|
static char first=1;
|
|
|
|
if (first) {
|
|
file=stderr;
|
|
first=0;
|
|
}
|
|
|
|
if (stdOutput==0) {
|
|
Nchars=Nlines=0;
|
|
if (gfile!=NULL) rewind(gfile);
|
|
}
|
|
|
|
if (flag==0)
|
|
{
|
|
char *ptr;
|
|
|
|
file=stderr;
|
|
flag = 1;
|
|
if ((ptr=getenv("FORTIFY_OUTPUT"))!=NULL)
|
|
{
|
|
if ((stricmp(ptr,"null")==0) || (stricmp(ptr,"nul")==0))
|
|
file=NULL;
|
|
else if (stricmp(ptr,"stderr")==0)
|
|
file=stderr;
|
|
else if (stricmp(ptr,"stdout")==0)
|
|
file=stdout;
|
|
#if defined MSDOS && !defined _WINDOWS && !defined WIN32
|
|
else if (stricmp(ptr,"stdprn")==0)
|
|
file=stdprn;
|
|
#endif
|
|
else if ((file=fopen(ptr,"w"))==NULL)
|
|
{
|
|
#if !defined _WINDOWS
|
|
fprintf(stderr,"\r\nFortify: Unable to create logfile %s\r\n",ptr);
|
|
EndOfPgr(4);
|
|
#else
|
|
{
|
|
char str[255];
|
|
|
|
sprintf(str,"Unable to create logfile\n \"%s\"",ptr);
|
|
MessageBox((HWND) NULL,(LPCSTR) str,(LPCSTR) "Fortify",(UINT) MB_ICONSTOP);
|
|
#if 0
|
|
#if defined WIN32
|
|
/* TerminateProcess(GetCurrentProcess(),65535); */
|
|
ExitProcess(65535);
|
|
#else
|
|
TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);
|
|
#endif
|
|
#else
|
|
EndOfPgr(1);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
if ((file!=NULL) && (file!=stderr) && (file!=stdout))
|
|
{
|
|
time_t t;
|
|
|
|
time(&t);
|
|
fprintf(file,"Generated on: %s%s\n",
|
|
ctime(&t),
|
|
(file==stdout) || (file==stderr) ? "\r" : ""
|
|
);
|
|
}
|
|
}
|
|
if (file!=NULL)
|
|
{
|
|
#if defined _WINDOWS
|
|
if ((file==stdout) || (file==stderr)) {
|
|
#if defined LINE_BY_LINE
|
|
if (MessageBox((HWND) NULL,(LPCSTR) String,(LPCSTR) "Fortify",(UINT) MB_OKCANCEL /* |MB_ICONINFORMATION */)==IDCANCEL)
|
|
#if 0
|
|
#if defined WIN32
|
|
/* TerminateProcess(GetCurrentProcess(),65535); */
|
|
ExitProcess(65535);
|
|
#else
|
|
TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);
|
|
#endif
|
|
#else
|
|
EndOfPgr(1);
|
|
#endif
|
|
#else
|
|
{
|
|
char *ptr;
|
|
|
|
ptr="fortify.tmp";
|
|
if ((ptr==NULL) || ((file=gfile=fopen(ptr,"w+"))==NULL))
|
|
{
|
|
char str[255];
|
|
|
|
sprintf(str,"Unable to create temporary file\n \"%s\"",(ptr==NULL) ? "(NULL)" : ptr);
|
|
MessageBox((HWND) NULL,(LPCSTR) str,(LPCSTR) "Fortify",(UINT) MB_ICONSTOP);
|
|
#if 0
|
|
#if defined WIN32
|
|
/* TerminateProcess(GetCurrentProcess(),65535); */
|
|
ExitProcess(65535);
|
|
#else
|
|
TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);
|
|
#endif
|
|
#else
|
|
EndOfPgr(1);
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
if ((file!=stdout) && (file!=stderr))
|
|
#endif
|
|
{
|
|
int i,ch=-1;
|
|
|
|
for (i=0;(String[i]) && (Nlines<30);i++)
|
|
if (String[i]=='\n') Nlines++;
|
|
if ((String[i]) && (String[i+1])) {
|
|
ch=String[i+1];
|
|
String[i+1]=0;
|
|
}
|
|
if ((file==stdout) || (file==stderr)) {
|
|
char *ptr=String;
|
|
int i;
|
|
|
|
do {
|
|
for (i=0;(ptr[i]) && (ptr[i]!='\r') && (ptr[i]!='\n');i++);
|
|
Nchars+=fprintf(file,"%-*.*s%s",
|
|
i,i,
|
|
ptr,
|
|
(ptr[i]) ? "\r\n" : ""
|
|
);
|
|
ptr+=i;
|
|
if (ptr[0]=='\r') ptr++;
|
|
if (ptr[0]=='\n') ptr++;
|
|
} while (*ptr);
|
|
}
|
|
else Nchars+=fprintf(file,String);
|
|
if (ch>=0) String[i+1]=(char)ch;
|
|
if (Nlines>=30) {
|
|
WaitIfstdOutput();
|
|
Nchars=Nlines=0;
|
|
stdOutput = 0;
|
|
if ((String[i]) && (String[i+1])) {
|
|
if ((file==stderr) || (file==stdout) || ((gfile!=NULL) && (Nchars)))
|
|
stdOutput = 1;
|
|
st_DefaultOutput(String+i);
|
|
}
|
|
}
|
|
}
|
|
if ((file==stderr) || (file==stdout) || ((gfile!=NULL) && (Nchars)))
|
|
stdOutput = 1;
|
|
}
|
|
}
|
|
|
|
static void WaitIfstdOutput()
|
|
{
|
|
#if !defined _WINDOWS
|
|
if((stdOutput) && (st_Output != (OutputFuncPtr) _Fortify_NoOutput))
|
|
{
|
|
#ifdef FORTIFY_WAIT_FOR_KEY
|
|
static signed char wait_on_key=-1;
|
|
|
|
if(wait_on_key<0)
|
|
{
|
|
char *ptr;
|
|
|
|
if (((ptr=getenv("FORTIFY_WAIT_FOR_KEY"))!=NULL) &&
|
|
(tolower(*ptr)=='n')) wait_on_key = 0;
|
|
else wait_on_key = 1;
|
|
|
|
}
|
|
if(wait_on_key)
|
|
{
|
|
char c;
|
|
|
|
#if !defined MSDOS && !defined WIN32
|
|
struct termio tio,tiobak;
|
|
char flag;
|
|
|
|
if ((flag=ioctl(0,TCGETA,&tio))==0) /* handle 0 is stdin */
|
|
{
|
|
tiobak=tio;
|
|
tio.c_lflag&=~ICANON;
|
|
tio.c_lflag&=~ECHO;
|
|
tio.c_cc[VMIN]=1;
|
|
ioctl(0,TCSETA,&tio);
|
|
}
|
|
#endif /* !MSDOS */
|
|
c = (char)getch();
|
|
|
|
#if !defined MSDOS && !defined WIN32
|
|
if (flag==0)
|
|
ioctl(0,TCSETA,&tiobak);
|
|
#endif /* !MSDOS */
|
|
|
|
if ((c == 3) || (c == 0x1b)) EndOfPgr(3);
|
|
}
|
|
#endif /* FORTIFY_WAIT_FOR_KEY */
|
|
|
|
}
|
|
#else
|
|
# if !defined LINE_BY_LINE
|
|
if ((stdOutput) && (gfile!=NULL) && (Nchars))
|
|
{
|
|
char *ptr;
|
|
|
|
ptr=(char *) malloc(Nchars+1);
|
|
if (ptr!=NULL)
|
|
{
|
|
int n=0,l=0;
|
|
|
|
rewind(gfile);
|
|
while ((n<Nchars) && (l<Nlines))
|
|
{
|
|
fgets(ptr+n,Nchars-n+1,gfile);
|
|
n+=(int)strlen(ptr+n);
|
|
l++;
|
|
}
|
|
if (MessageBox((HWND) NULL,(LPCSTR) ptr,(LPCSTR) "Fortify",(UINT) MB_OKCANCEL /* |MB_ICONINFORMATION */)==IDCANCEL)
|
|
#if 0
|
|
#if defined WIN32
|
|
/* TerminateProcess(GetCurrentProcess(),65535); */
|
|
ExitProcess(65535);
|
|
#else
|
|
TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);
|
|
#endif
|
|
#else
|
|
EndOfPgr(1);
|
|
#endif
|
|
}
|
|
free(ptr);
|
|
}
|
|
# endif
|
|
#endif
|
|
stdOutput = 0;
|
|
}
|
|
|
|
static struct Header *st_Head = NULL; /* Head of alloc'd memory list */
|
|
static char st_Buffer[256]; /* Temporary buffer for sprintf's */
|
|
static int st_Disabled = 0; /* If true, Fortify is inactive */
|
|
static int st_MallocFailRate = 0; /* % of the time to fail mallocs */
|
|
|
|
static char *st_LastVerifiedFile = "unknown";
|
|
static unsigned short st_LastVerifiedLine = 0;
|
|
static unsigned char st_Scope = 0;
|
|
static void OutputLastVerifiedPoint __OF((void));
|
|
|
|
void FORTIFY_STORAGE
|
|
_Fortify_Init(char *file,unsigned long line)
|
|
{
|
|
if (gfile!=NULL) fclose(gfile);
|
|
gfile=NULL;
|
|
Nchars=Nlines=0;
|
|
flag=0;
|
|
st_Head=NULL;
|
|
stdOutput=0;
|
|
st_Output=st_DefaultOutput;
|
|
st_Disabled=0;
|
|
st_MallocFailRate=0;
|
|
st_LastVerifiedFile="unknown";
|
|
st_LastVerifiedLine=0;
|
|
st_Scope=0;
|
|
}
|
|
|
|
|
|
/*
|
|
* _Fortify_malloc() - Allocates a block of memory, with extra bits for
|
|
* misuse protection/detection.
|
|
*
|
|
* Features:
|
|
* + Adds the malloc'd memory onto Fortify's own private list.
|
|
* (With a checksum'd header to detect corruption of the memory list)
|
|
* + Places sentinals on either side of the user's memory with
|
|
* known data in them, to detect use outside of the bounds
|
|
* of the block
|
|
* + Initializes the malloc'd memory to some "nasty" value, so code
|
|
* can't rely on it's contents.
|
|
* + Can check all sentinals on every malloc.
|
|
* + Can generate a warning message on a malloc fail.
|
|
* + Can randomly "fail" at a set fail rate
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_malloc(size_t size,char *file,unsigned long line)
|
|
{
|
|
unsigned char *ptr;
|
|
struct Header *h;
|
|
|
|
stdOutput = 0;
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
if(st_Disabled)
|
|
{
|
|
ptr = (unsigned char *) malloc(size);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return((void *) ptr);
|
|
}
|
|
|
|
#ifdef CHECK_ALL_MEMORY_ON_MALLOC
|
|
#ifdef FORTIFY_CheckInterval
|
|
if (TimeToCheck())
|
|
#endif
|
|
_Fortify_CheckAllMemory(file, line);
|
|
#endif
|
|
|
|
if(size == 0)
|
|
{
|
|
#ifdef WARN_ON_ZERO_MALLOC
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n malloc(0) attempted failed\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
#endif
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if(st_MallocFailRate > 0)
|
|
{
|
|
if(rand() % 100 < st_MallocFailRate)
|
|
{
|
|
#ifdef WARN_ON_FALSE_FAIL
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n malloc(%ld) \"false\" failed\n",
|
|
file, line, (unsigned long)size);
|
|
st_Output(st_Buffer);
|
|
#endif
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* malloc the memory, including the space for the header and fortification
|
|
* buffers
|
|
*/
|
|
#ifdef WARN_ON_SIZE_T_OVERFLOW
|
|
{
|
|
size_t private_size = sizeof(struct Header)
|
|
+ FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE;
|
|
|
|
if(private_size < size) /* Check to see if the added baggage is larger than size_t */
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n malloc(%ld) has overflowed size_t.\n",
|
|
file, line, (unsigned long)size);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ptr = (unsigned char *) malloc(sizeof(struct Header) +
|
|
FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE);
|
|
if(!ptr)
|
|
{
|
|
#ifdef WARN_ON_MALLOC_FAIL
|
|
sprintf(st_Buffer, "\nFortify: %s.%ld\n malloc(%ld) failed\n",
|
|
file, line, (unsigned long)size);
|
|
st_Output(st_Buffer);
|
|
#endif
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Initialize and validate the header
|
|
*/
|
|
h = (struct Header *)ptr;
|
|
|
|
h->Size = size;
|
|
|
|
h->File = file;
|
|
h->Line = (unsigned short) line;
|
|
|
|
h->Next = st_Head;
|
|
h->Prev = 0;
|
|
|
|
h->Scope = st_Scope;
|
|
|
|
if(st_Head)
|
|
{
|
|
st_Head->Prev = h;
|
|
MakeHeaderValid(st_Head);
|
|
}
|
|
|
|
st_Head = h;
|
|
|
|
MakeHeaderValid(h);
|
|
|
|
|
|
/*
|
|
* Initialize the fortifications
|
|
*/
|
|
SetFortification(ptr + sizeof(struct Header),
|
|
FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE);
|
|
SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + size,
|
|
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
|
|
|
|
#ifdef FILL_ON_MALLOC
|
|
/*
|
|
* Fill the actual user memory
|
|
*/
|
|
SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE,
|
|
FILL_ON_MALLOC_VALUE, size);
|
|
#endif
|
|
|
|
/*
|
|
* We return the address of the user's memory, not the start of the block,
|
|
* which points to our magic cookies
|
|
*/
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return((void *) (ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE));
|
|
}
|
|
|
|
/*
|
|
* _Fortify_free() - This free must be used for all memory allocated with
|
|
* _Fortify_malloc().
|
|
*
|
|
* Features:
|
|
* + Pointers are validated before attempting a free - the pointer
|
|
* must point to a valid malloc'd bit of memory.
|
|
* + Detects attempts at freeing the same block of memory twice
|
|
* + Can clear out memory as it is free'd, to prevent code from using
|
|
* the memory after it's been freed.
|
|
* + Checks the sentinals of the memory being freed.
|
|
* + Can check the sentinals of all memory.
|
|
*/
|
|
|
|
void FORTIFY_STORAGE
|
|
_Fortify_free(void *uptr,char *file,unsigned long line)
|
|
{
|
|
unsigned char *ptr;
|
|
struct Header *h;
|
|
|
|
if(uptr == NULL)
|
|
return;
|
|
|
|
ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE;
|
|
h = (struct Header *)ptr;
|
|
|
|
stdOutput = 0;
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
if(st_Disabled)
|
|
{
|
|
free(uptr);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return;
|
|
}
|
|
|
|
#ifdef CHECK_ALL_MEMORY_ON_FREE
|
|
#ifdef FORTIFY_CheckInterval
|
|
if (TimeToCheck())
|
|
#endif
|
|
_Fortify_CheckAllMemory(file, line);
|
|
#endif
|
|
|
|
#ifdef PARANOID_FREE
|
|
if(!IsOnList(h))
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n Invalid pointer, corrupted header, or possible free twice\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
OutputLastVerifiedPoint();
|
|
goto fail;
|
|
}
|
|
#endif
|
|
|
|
if(!CheckBlock(h, file, line))
|
|
goto fail;
|
|
|
|
/*
|
|
* Remove the block from the list
|
|
*/
|
|
if(h->Prev)
|
|
{
|
|
if(!CheckBlock(h->Prev, file, line))
|
|
goto fail;
|
|
|
|
h->Prev->Next = h->Next;
|
|
MakeHeaderValid(h->Prev);
|
|
}
|
|
else
|
|
st_Head = h->Next;
|
|
|
|
if(h->Next)
|
|
{
|
|
if(!CheckBlock(h->Next, file, line))
|
|
goto fail;
|
|
|
|
h->Next->Prev = h->Prev;
|
|
MakeHeaderValid(h->Next);
|
|
}
|
|
|
|
#ifdef FILL_ON_FREE
|
|
/*
|
|
* Nuke out all memory that is about to be freed
|
|
*/
|
|
SetFortification(ptr, FILL_ON_FREE_VALUE,
|
|
sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size + FORTIFY_AFTER_SIZE);
|
|
#endif
|
|
|
|
/*
|
|
* And do the actual free
|
|
*/
|
|
free(ptr);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return;
|
|
|
|
fail:
|
|
sprintf(st_Buffer, " free(%s) failed\n", address(uptr));
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
}
|
|
|
|
/*
|
|
* _Fortify_realloc() - Uses _Fortify_malloc() and _Fortify_free() to implement
|
|
* realloc().
|
|
*
|
|
* Features:
|
|
* + The realloc'd block is ALWAYS moved.
|
|
* + The pointer passed to realloc() is verified in the same way that
|
|
* _Fortify_free() verifies pointers before it frees them.
|
|
* + All the _Fortify_malloc() and _Fortify_free() protection
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_realloc(void *ptr,size_t new_size,char *file,unsigned long line)
|
|
{
|
|
void *new_ptr;
|
|
struct Header *h;
|
|
|
|
if(new_size == 0)
|
|
{
|
|
_Fortify_free(ptr,file,line);
|
|
return(NULL);
|
|
}
|
|
|
|
h = (struct Header *)((unsigned char *)ptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE);
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
FORTIFY_LOCK();
|
|
new_ptr = (void *) realloc(ptr, new_size);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(new_ptr);
|
|
}
|
|
|
|
if(!ptr)
|
|
{
|
|
void *FORTIFY_STORAGE ret = _Fortify_malloc(new_size, file, line);
|
|
|
|
WaitIfstdOutput();
|
|
return(ret);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
if(!IsOnList(h))
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n Invalid pointer or corrupted header passed to realloc\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
goto fail;
|
|
}
|
|
|
|
if(!CheckBlock(h, file, line))
|
|
goto fail;
|
|
|
|
new_ptr = _Fortify_malloc(new_size, file, line);
|
|
if(!new_ptr)
|
|
{
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if(h->Size < new_size)
|
|
memcpy(new_ptr, ptr, h->Size);
|
|
else
|
|
memcpy(new_ptr, ptr, new_size);
|
|
|
|
_Fortify_free(ptr, file, line);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(new_ptr);
|
|
|
|
fail:
|
|
sprintf(st_Buffer, " realloc(%s, %ld) failed\n", address(ptr), (unsigned long)new_size);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* __Fortify_CheckPointer() - Returns true if the uptr points to a valid
|
|
* piece of _Fortify_malloc()'d memory. The memory must be on the malloc'd
|
|
* list, and it's sentinals must be in tact.
|
|
* If anything is wrong, an error message is issued.
|
|
*
|
|
* (Note - if fortify is disabled, this function always returns true).
|
|
*/
|
|
static int FORTIFY_STORAGE
|
|
__Fortify_CheckPointer(void *uptr,char OnlyStart,unsigned long size,char *file,unsigned long line)
|
|
{
|
|
unsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE;
|
|
int r = 1, StartPointer;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
WaitIfstdOutput();
|
|
return(1);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
StartPointer = IsOnList((struct Header *)ptr);
|
|
if((OnlyStart) && (!StartPointer))
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%s)\n",
|
|
file, line, address(uptr));
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if((OnlyStart) || (StartPointer))
|
|
r = CheckBlock((struct Header *)ptr, file, line);
|
|
if(!OnlyStart)
|
|
r = CheckPointer((unsigned char *)uptr, size, file, line);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(r);
|
|
}
|
|
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_CheckPointer(void *uptr,char *file,unsigned long line)
|
|
{
|
|
return(__Fortify_CheckPointer(uptr,1,0,file,line));
|
|
}
|
|
|
|
/*
|
|
* Fortify_SetOutputFunc(OutputFuncPtr Output) - Sets the function used to
|
|
* output all error and diagnostic messages by fortify. The output function
|
|
* takes a single unsigned char * argument, and must be able to handle newlines.
|
|
* The function returns the old pointer.
|
|
*/
|
|
Fortify_OutputFuncPtr FORTIFY_STORAGE
|
|
_Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output)
|
|
{
|
|
OutputFuncPtr Old = st_Output;
|
|
|
|
st_Output = (OutputFuncPtr) Output;
|
|
|
|
return((Fortify_OutputFuncPtr FORTIFY_STORAGE) Old);
|
|
}
|
|
|
|
/*
|
|
* _Fortify_SetMallocFailRate(int Percent) - _Fortify_malloc() will make the
|
|
* malloc attempt fail this Percent of the time, even if the memory is
|
|
* available. Useful to "stress-test" an application. Returns the old
|
|
* value. The fail rate defaults to 0.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_SetMallocFailRate(int Percent)
|
|
{
|
|
int Old = st_MallocFailRate;
|
|
|
|
st_MallocFailRate = Percent;
|
|
|
|
return(Old);
|
|
}
|
|
|
|
|
|
/*
|
|
* _Fortify_CheckAllMemory() - Checks the sentinals of all malloc'd memory.
|
|
* Returns the number of blocks that failed.
|
|
*
|
|
* (If Fortify is disabled, this function always returns 0).
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_CheckAllMemory(char *file,unsigned long line)
|
|
{
|
|
struct Header *curr = st_Head;
|
|
int count = 0;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
while(curr)
|
|
{
|
|
if(!CheckBlock(curr, file, line))
|
|
count++;
|
|
|
|
curr = curr->Next;
|
|
}
|
|
|
|
if(file)
|
|
{
|
|
st_LastVerifiedFile = file;
|
|
st_LastVerifiedLine = (short) line;
|
|
}
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(count);
|
|
}
|
|
|
|
/* _Fortify_EnterScope - enters a new Fortify scope level.
|
|
* returns the new scope level.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_EnterScope(char *file,unsigned long line)
|
|
{
|
|
return((int) ++st_Scope);
|
|
}
|
|
|
|
/* _Fortify_LeaveScope - leaves a Fortify scope level,
|
|
* also prints a memory dump of all non-freed memory that was allocated
|
|
* during the scope being exited.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_LeaveScope(char *file,unsigned long line)
|
|
{
|
|
struct Header *curr = st_Head;
|
|
int count = 0;
|
|
size_t size = 0;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
st_Scope--;
|
|
while(curr)
|
|
{
|
|
if(curr->Scope > st_Scope)
|
|
{
|
|
if(count == 0)
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line);
|
|
st_Output(st_Buffer);
|
|
OutputLastVerifiedPoint();
|
|
sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator");
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
OutputHeader(curr);
|
|
count++;
|
|
size += curr->Size;
|
|
}
|
|
|
|
curr = curr->Next;
|
|
}
|
|
|
|
if(count)
|
|
{
|
|
sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and",
|
|
(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(count);
|
|
}
|
|
|
|
/*
|
|
* _Fortify_OutputAllMemory() - Outputs the entire list of currently
|
|
* malloc'd memory. For each malloc'd block is output it's Address,
|
|
* Size, and the SourceFile and Line that allocated it.
|
|
*
|
|
* If there is no memory on the list, this function outputs nothing.
|
|
*
|
|
* It returns the number of blocks on the list, unless fortify has been
|
|
* disabled, in which case it always returns 0.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_OutputAllMemory(char *file,unsigned long line)
|
|
{
|
|
struct Header *curr = st_Head;
|
|
int count = 0;
|
|
size_t size = 0;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
if(curr)
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line);
|
|
st_Output(st_Buffer);
|
|
OutputLastVerifiedPoint();
|
|
sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator");
|
|
st_Output(st_Buffer);
|
|
|
|
while(curr)
|
|
{
|
|
OutputHeader(curr);
|
|
count++;
|
|
size += curr->Size;
|
|
curr = curr->Next;
|
|
}
|
|
|
|
sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and",
|
|
(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(count);
|
|
}
|
|
|
|
/* _Fortify_DumpAllMemory(Scope) - Outputs the entire list of currently
|
|
* new'd memory within the specified scope. For each new'd block is output
|
|
* it's Address, Size, the SourceFile and Line that allocated it, a hex dump
|
|
* of the contents of the memory and an ascii dump of printable characters.
|
|
*
|
|
* If there is no memory on the list, this function outputs nothing.
|
|
*
|
|
* It returns the number of blocks on the list, unless Fortify has been
|
|
* disabled, in which case it always returns 0.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_DumpAllMemory(int scope,char *file,unsigned long line)
|
|
{
|
|
struct Header *curr = st_Head;
|
|
int count = 0;
|
|
size_t size = 0;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(st_Disabled)
|
|
{
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
while(curr)
|
|
{
|
|
if(curr->Scope >= scope)
|
|
{
|
|
if(count == 0)
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line);
|
|
st_Output(st_Buffer);
|
|
OutputLastVerifiedPoint();
|
|
sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator");
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
OutputHeader(curr);
|
|
OutputMemory(curr);
|
|
st_Output("\n");
|
|
count++;
|
|
size += curr->Size;
|
|
}
|
|
|
|
curr = curr->Next;
|
|
}
|
|
|
|
if(count)
|
|
{
|
|
sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and",
|
|
(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(count);
|
|
}
|
|
|
|
/*
|
|
* _Fortify_Disable() - This function provides a mechanism to disable Fortify
|
|
* without recompiling all the sourcecode.
|
|
* If 'how' is zero then it can only be called when there is no memory on the
|
|
* Fortify malloc'd list. (Ideally, at the start of the program before any
|
|
* memory has been allocated). If you call this function when there IS
|
|
* memory on the Fortify malloc'd list, it will issue an error, and fortify
|
|
* will not be disabled.
|
|
* If 'how' is nonzero then output will only be disabled. This can always be
|
|
* done.
|
|
*/
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_Disable(char *file,unsigned long line,int how)
|
|
{
|
|
int result;
|
|
|
|
if (how <= 0)
|
|
{
|
|
stdOutput = 0;
|
|
|
|
FORTIFY_LOCK();
|
|
|
|
if((st_Head) && (how == 0))
|
|
{
|
|
sprintf(st_Buffer, "Fortify: %s.%d\n", file, line);
|
|
st_Output(st_Buffer);
|
|
st_Output(" Fortify_Disable failed\n");
|
|
st_Output(" (because there is memory on the Fortify memory list)\n");
|
|
|
|
_Fortify_OutputAllMemory(file, line);
|
|
result = 0;
|
|
}
|
|
else
|
|
{
|
|
st_Disabled = (how >= -1 ? 1 : 0);
|
|
result = 1;
|
|
}
|
|
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
}
|
|
else
|
|
{
|
|
_Fortify_SetOutputFunc((Fortify_OutputFuncPtr) _Fortify_NoOutput);
|
|
result = 1;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
/*
|
|
* Check a block's header and fortifications.
|
|
*/
|
|
static int CheckBlock(struct Header *h,char *file,unsigned long line)
|
|
{
|
|
unsigned char *ptr = (unsigned char *)h;
|
|
int result = 1;
|
|
|
|
stdOutput = 0;
|
|
|
|
if(!IsHeaderValid(h))
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%s)\n",
|
|
file, line, address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE));
|
|
st_Output(st_Buffer);
|
|
OutputLastVerifiedPoint();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if(!CheckFortification(ptr + sizeof(struct Header),
|
|
FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE))
|
|
{
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n Memory overrun detected before block\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer," (%s,%ld,%s.%u)\n",
|
|
address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),
|
|
(unsigned long)h->Size, h->File, h->Line);
|
|
st_Output(st_Buffer);
|
|
|
|
OutputFortification(ptr + sizeof(struct Header),
|
|
FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE);
|
|
OutputLastVerifiedPoint();
|
|
result = 0;
|
|
}
|
|
|
|
if(!CheckFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size,
|
|
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: %s.%ld\n Memory overrun detected after block\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer," (%s,%ld,%s.%u)\n",
|
|
address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),
|
|
(unsigned long)h->Size, h->File, h->Line);
|
|
st_Output(st_Buffer);
|
|
|
|
OutputFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size,
|
|
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
|
|
OutputLastVerifiedPoint();
|
|
result = 0;
|
|
}
|
|
|
|
WaitIfstdOutput();
|
|
return(result);
|
|
}
|
|
|
|
static int CheckPointer(unsigned char *ptr,unsigned long size,char *file,unsigned long line)
|
|
{
|
|
struct Header *curr;
|
|
unsigned char *ptr1;
|
|
|
|
curr = st_Head;
|
|
while(curr)
|
|
{
|
|
ptr1 = (unsigned char *)curr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE;
|
|
if(ptr + size <= (unsigned char *)curr)
|
|
;
|
|
else if(ptr >= ptr1)
|
|
;
|
|
else
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: %s.%ld\n Memory access detected before block\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer," (%s,%ld,%s.%u)\n",
|
|
address(ptr1),
|
|
(unsigned long)curr->Size, curr->File, curr->Line);
|
|
st_Output(st_Buffer);
|
|
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if(ptr + size <= ptr1 + curr->Size)
|
|
;
|
|
else if(ptr >= ptr1 + curr->Size + FORTIFY_AFTER_SIZE)
|
|
;
|
|
else
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: %s.%ld\n Memory access detected after block\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer," (%s,%ld,%s.%u)\n",
|
|
address(ptr1),
|
|
(unsigned long)curr->Size, curr->File, curr->Line);
|
|
st_Output(st_Buffer);
|
|
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
if((ptr >= ptr1) && (ptr < ptr1 + curr->Size) && (ptr + size > ptr1 + curr->Size))
|
|
{
|
|
sprintf(st_Buffer, "\nFortify: %s.%ld\n Memory access detected after block\n",
|
|
file, line);
|
|
st_Output(st_Buffer);
|
|
|
|
sprintf(st_Buffer," (%s,%ld,%s.%u)\n",
|
|
address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),
|
|
(unsigned long)curr->Size, curr->File, curr->Line);
|
|
st_Output(st_Buffer);
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
curr = curr->Next;
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Checks if the _size_ bytes from _ptr_ are all set to _value_
|
|
*/
|
|
static int CheckFortification(unsigned char *ptr,unsigned char value,size_t size)
|
|
{
|
|
while(size--)
|
|
if(*ptr++ != value)
|
|
return(0);
|
|
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Set the _size_ bytes from _ptr_ to _value_.
|
|
*/
|
|
static void SetFortification(unsigned char *ptr,unsigned char value,size_t size)
|
|
{
|
|
memset(ptr, value, size);
|
|
}
|
|
|
|
/*
|
|
* Output the corrupted section of the fortification
|
|
*/
|
|
/* Output the corrupted section of the fortification */
|
|
static void
|
|
OutputFortification(unsigned char *ptr,unsigned char value,size_t size)
|
|
{
|
|
unsigned long offset, column;
|
|
char ascii[17];
|
|
|
|
st_Output("Address Offset Data");
|
|
|
|
offset = 0;
|
|
column = 0;
|
|
|
|
while(offset < size)
|
|
{
|
|
if(column == 0)
|
|
{
|
|
sprintf(st_Buffer, "\n%8s %8d ", address(ptr), offset);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
sprintf(st_Buffer, "%02x ", *ptr);
|
|
st_Output(st_Buffer);
|
|
|
|
ascii[ (int) column ] = isprint( *ptr ) ? (char)(*ptr) : (char)(' ');
|
|
ascii[ (int) (column + 1) ] = '\0';
|
|
|
|
ptr++;
|
|
offset++;
|
|
column++;
|
|
|
|
if(column == 16)
|
|
{
|
|
st_Output( " \"" );
|
|
st_Output( ascii );
|
|
st_Output( "\"" );
|
|
column = 0;
|
|
}
|
|
}
|
|
|
|
if ( column != 0 )
|
|
{
|
|
while ( column ++ < 16 )
|
|
{
|
|
st_Output( " " );
|
|
}
|
|
st_Output( " \"" );
|
|
st_Output( ascii );
|
|
st_Output( "\"" );
|
|
}
|
|
|
|
st_Output("\n");
|
|
}
|
|
|
|
/*
|
|
* Returns true if the supplied pointer does indeed point to a real Header
|
|
*/
|
|
static int IsHeaderValid(struct Header *h)
|
|
{
|
|
return(!ChecksumHeader(h));
|
|
}
|
|
|
|
/*
|
|
* Updates the checksum to make the header valid
|
|
*/
|
|
static void MakeHeaderValid(struct Header *h)
|
|
{
|
|
h->Checksum = 0;
|
|
h->Checksum = -ChecksumHeader(h);
|
|
}
|
|
|
|
/*
|
|
* Calculate (and return) the checksum of the header. (Including the Checksum
|
|
* variable itself. If all is well, the checksum returned by this function should
|
|
* be 0.
|
|
*/
|
|
static int ChecksumHeader(struct Header *h)
|
|
{
|
|
register int c, checksum, *p;
|
|
|
|
for(c = 0, checksum = 0, p = (int *)h; c < sizeof(struct Header)/sizeof(int); c++)
|
|
checksum += *p++;
|
|
|
|
return(checksum);
|
|
}
|
|
|
|
/*
|
|
* Examines the malloc'd list to see if the given header is on it.
|
|
*/
|
|
static int IsOnList(struct Header *h)
|
|
{
|
|
struct Header *curr;
|
|
|
|
curr = st_Head;
|
|
while(curr)
|
|
{
|
|
if(curr == h)
|
|
return(1);
|
|
curr = curr->Next;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Hex and ascii dump the memory
|
|
*/
|
|
static void
|
|
OutputMemory(struct Header *h)
|
|
{
|
|
OutputFortification((unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE,
|
|
0, h->Size);
|
|
}
|
|
|
|
|
|
/*
|
|
* Output the header...
|
|
*/
|
|
static void OutputHeader(struct Header *h)
|
|
{
|
|
sprintf(st_Buffer, "%11s %8ld %s.%u (%d)\n",
|
|
address((unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),
|
|
(unsigned long)h->Size,
|
|
h->File, h->Line, (int) h->Scope);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
static void OutputLastVerifiedPoint()
|
|
{
|
|
sprintf(st_Buffer, "\nLast Verified point: %s.%u\n",
|
|
st_LastVerifiedFile,
|
|
st_LastVerifiedLine);
|
|
st_Output(st_Buffer);
|
|
}
|
|
|
|
#else /* FORTIFY_TRANSPARENT */
|
|
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_malloc(size,file,line)
|
|
size_t size;
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(malloc(size));
|
|
}
|
|
|
|
void FORTIFY_STORAGE
|
|
_Fortify_free(uptr,file,line)
|
|
void *uptr;
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
free(uptr);
|
|
}
|
|
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_realloc(ptr,new_size,file,line)
|
|
void *ptr;
|
|
size_t new_size;
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(realloc(ptr, new_size));
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_CheckPointer(uptr,file,line)
|
|
void *uptr;
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
Fortify_OutputFuncPtr FORTIFY_STORAGE
|
|
_Fortify_SetOutputFunc(Output)
|
|
Fortify_OutputFuncPtr Output;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_SetMallocFailRate(Percent)
|
|
int Percent;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_CheckAllMemory(file,line)
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_EnterScope(file,line)
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_LeaveScope(file,line)
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_OutputAllMemory(file,line)
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_DumpAllMemory(scope,file,line)
|
|
int scope;
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int FORTIFY_STORAGE
|
|
_Fortify_Disable(file,line)
|
|
char *file;
|
|
unsigned long line;
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
#endif /* !FORTIFY_TRANSPARENT */
|
|
|
|
/* function that use _Fortify_malloc(), _Fortify_realloc(), _Fortify_free() */
|
|
|
|
/*
|
|
* Fortifty_calloc() - Uses _Fortify_malloc() to implement calloc(). Much
|
|
* the same protection as _Fortify_malloc().
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_calloc(size_t nitems,size_t size,char *file,unsigned long line)
|
|
{
|
|
void *ptr;
|
|
|
|
ptr = _Fortify_malloc(nitems * size, file, line);
|
|
|
|
if(ptr)
|
|
memset(ptr, 0, nitems * size);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/*
|
|
* Fortifty_strdup() - Uses _Fortify_malloc() to implement strdup(). Much
|
|
* the same protection as _Fortify_malloc().
|
|
* The library function is not used because it is not certain that getpwd
|
|
* uses the library malloc function (if linked with an alternate library)
|
|
* and if the memory is freed then strange things can happen
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strdup(char *str,char *file,unsigned long line)
|
|
{
|
|
char *ptr;
|
|
unsigned long l;
|
|
|
|
if(str == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strdup pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
l = (int) strlen(str) + 1;
|
|
__Fortify_CheckPointer(str,0,l,file,line);
|
|
|
|
ptr = (char *) _Fortify_malloc(l, file, line);
|
|
|
|
if(ptr)
|
|
strcpy(ptr, str);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/*
|
|
* Fortifty_getpwd() - Uses _Fortify_malloc() to implement getpwd(). Much
|
|
* the same protection as _Fortify_malloc().
|
|
* Memory is not allocated bu getcwd but by our routine for the same reason
|
|
* as for strdup
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_getcwd(char *buf,int size,char *file,unsigned long line)
|
|
{
|
|
char *ptr;
|
|
|
|
if(buf!=NULL)
|
|
ptr = buf;
|
|
else
|
|
ptr = (char *) _Fortify_malloc(size + 1, file, line);
|
|
|
|
if(ptr)
|
|
ptr = getcwd(ptr, size);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/*
|
|
* Fortifty_tempnam() - Uses _Fortify_strdup() to implement tempnam(). Much
|
|
* the same protection as _Fortify_malloc().
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_tempnam(char *dir,char *pfx,char *file,unsigned long line)
|
|
{
|
|
char *ptr1, *ptr2;
|
|
|
|
ptr1 = tempnam(dir,pfx);
|
|
|
|
if(ptr1)
|
|
{
|
|
ptr2=_Fortify_strdup(ptr1,file,line);
|
|
free(ptr1);
|
|
ptr1=ptr2;
|
|
}
|
|
|
|
return(ptr1);
|
|
}
|
|
|
|
/*
|
|
* Fortify_memcpy() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_memcpy(void *to,void *from,size_t size,char *file,unsigned long line)
|
|
{
|
|
if (size) {
|
|
if((from == NULL) || (to == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(from == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "memcpy from pointer is NULL", file, line);
|
|
if(to == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (from == NULL) ? "" : " and ", "memcpy to pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(to,0,size,file,line);
|
|
__Fortify_CheckPointer(from,0,size,file,line);
|
|
}
|
|
return(memcpy(to,from,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memmove() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_memmove(void *to,void *from,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((from == NULL) || (to == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(from == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "memmove from pointer is NULL", file, line);
|
|
if(to == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (from == NULL) ? "" : " and ", "memmove to pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(to,0,size,file,line);
|
|
__Fortify_CheckPointer(from,0,size,file,line);
|
|
return(memmove(to,from,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memccpy() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_memccpy(void *to,void *from,int c,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((from == NULL) || (to == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(from == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "memccpy from pointer is NULL", file, line);
|
|
if(to == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (from == NULL) ? "" : " and ", "memccpy to pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(to,0,size,file,line);
|
|
__Fortify_CheckPointer(from,0,size,file,line);
|
|
return(memccpy(to,from,c,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memset() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_memset(void *buffer,int c,size_t size,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n memset pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,size,file,line);
|
|
return(memset(buffer,c,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memchr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
void *FORTIFY_STORAGE
|
|
_Fortify_memchr(void *buffer,int c,size_t size,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n memchr pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,size,file,line);
|
|
return(memchr(buffer,c,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memcmp() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_memcmp(void *buffer1,void *buffer2,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "memcmp first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "memcmp second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,size,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,size,file,line);
|
|
return(memcmp(buffer1,buffer2,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_memicmp() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_memicmp(void *buffer1,void *buffer2,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "memicmp first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "memicmp second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,size,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,size,file,line);
|
|
return(memicmp(buffer1,buffer2,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strcoll() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_strcoll(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strcoll first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strcoll second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);
|
|
return(strcoll(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strcspn() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
size_t FORTIFY_STORAGE
|
|
_Fortify_strcspn(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strcspn first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strcspn second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);
|
|
return(strcspn(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strcmp() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_strcmp(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strcmp first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strcmp second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);
|
|
return(strcmp(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strcmpi() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_strcmpi(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strcmpi first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strcmpi second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);
|
|
return(strcmpi(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strncmp() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_strncmp(char *buffer1,char *buffer2,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strncmp first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strncmp second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,MIN(strlen(buffer1)+1,size),file,line);
|
|
__Fortify_CheckPointer(buffer2,0,MIN(strlen(buffer2)+1,size),file,line);
|
|
return(strncmp(buffer1,buffer2,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strnicmp() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_strnicmp(char *buffer1,char *buffer2,size_t size,char *file,unsigned long line)
|
|
{
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strnicmp first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strnicmp second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,MIN(strlen(buffer1)+1,size),file,line);
|
|
__Fortify_CheckPointer(buffer2,0,MIN(strlen(buffer2)+1,size),file,line);
|
|
return(strnicmp(buffer1,buffer2,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strchr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strchr(char *buffer,int c,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strchr pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strchr(buffer,c));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strrchr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strrchr(char *buffer,int c,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strchr pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strrchr(buffer,c));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strlwr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strlwr(char *buffer,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strlwr pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strlwr(buffer));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strlwr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strupr(char *buffer,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strupr pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strupr(buffer));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strrev() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strrev(char *buffer,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strrev pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strrev(buffer));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strlen() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
size_t FORTIFY_STORAGE
|
|
_Fortify_strlen(char *buffer,char *file,unsigned long line)
|
|
{
|
|
unsigned long l;
|
|
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strlen pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
l = strlen(buffer);
|
|
__Fortify_CheckPointer(buffer,0,l+1,file,line);
|
|
return(l);
|
|
}
|
|
|
|
/*
|
|
* Fortify_strcat() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strcat(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
unsigned long l;
|
|
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strcat first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strcat second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
l = strlen(buffer2)+1;
|
|
__Fortify_CheckPointer(buffer1,0,l,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,l,file,line);
|
|
return(strcat(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strpbrk() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strpbrk(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
unsigned long l;
|
|
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strpbrk first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strpbrk second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
l = strlen(buffer2)+1;
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,l,file,line);
|
|
return(strpbrk(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strstr() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strstr(char *buffer1,char *buffer2,char *file,unsigned long line)
|
|
{
|
|
unsigned long l;
|
|
|
|
if((buffer1 == NULL) || (buffer2 == NULL)) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
if(buffer1 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strstr first pointer is NULL", file, line);
|
|
if(buffer2 == NULL)
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s%s", (buffer2 == NULL) ? "" : " and ", "strstr second pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
l = strlen(buffer2)+1;
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
__Fortify_CheckPointer(buffer2,0,l,file,line);
|
|
return(strstr(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strtol() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
long FORTIFY_STORAGE
|
|
_Fortify_strtol(char *buffer1,char **buffer2,int n,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strtol first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(strtol(buffer1,buffer2,n));
|
|
}
|
|
|
|
/*
|
|
* Fortify_atoi() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
int FORTIFY_STORAGE
|
|
_Fortify_atoi(char *buffer1,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "atoi first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(atoi(buffer1));
|
|
}
|
|
|
|
/*
|
|
* Fortify_atol() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
long FORTIFY_STORAGE
|
|
_Fortify_atol(char *buffer1,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "atol first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(atol(buffer1));
|
|
}
|
|
|
|
/*
|
|
* Fortify_atod() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
double FORTIFY_STORAGE
|
|
_Fortify_atof(char *buffer1,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "atod first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(atof(buffer1));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strtoul() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
unsigned long FORTIFY_STORAGE
|
|
_Fortify_strtoul(char *buffer1,char **buffer2,int n,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strtoul first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(strtoul(buffer1,buffer2,n));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strtod() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
double FORTIFY_STORAGE
|
|
_Fortify_strtod(char *buffer1,char **buffer2,char *file,unsigned long line)
|
|
{
|
|
if(buffer1 == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n ", file, line);
|
|
sprintf(st_Buffer + strlen(st_Buffer), "%s", "strtod first pointer is NULL", file, line);
|
|
strcat(st_Buffer, "\n");
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(0);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);
|
|
return(strtod(buffer1,buffer2));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strset() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strset(char *buffer,int c,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strset pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strset(buffer,c));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strnset() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strnset(char *buffer,int c,size_t size,char *file,unsigned long line)
|
|
{
|
|
if(buffer == NULL) {
|
|
sprintf(st_Buffer,
|
|
"\nFortify: %s.%ld\n strnset pointer is NULL\n", file, line);
|
|
st_Output(st_Buffer);
|
|
FORTIFY_UNLOCK();
|
|
WaitIfstdOutput();
|
|
return(NULL);
|
|
}
|
|
|
|
__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);
|
|
return(strnset(buffer,c,size));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strncpy() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
static char *FORTIFY_STORAGE
|
|
__Fortify_strncpy(char *to,char *from,size_t size,int usesize,char *file,unsigned long line)
|
|
{
|
|
size_t size1;
|
|
|
|
size1 = strlen(from) + 1;
|
|
if(usesize)
|
|
{
|
|
if(size < size1)
|
|
size1 = size;
|
|
}
|
|
|
|
return((char *) _Fortify_memcpy(to,from,size1,file,line));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strncpy() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strncpy(char *to,char *from,size_t size,char *file,unsigned long line)
|
|
{
|
|
return(__Fortify_strncpy(to,from,size,1,file,line));
|
|
}
|
|
|
|
/*
|
|
* Fortify_strncpy() - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.
|
|
*/
|
|
char *FORTIFY_STORAGE
|
|
_Fortify_strcpy(char *to,char *from,char *file,unsigned long line)
|
|
{
|
|
return(__Fortify_strncpy(to,from,0,0,file,line));
|
|
}
|
|
|
|
#endif /* FORTIFY */
|