📄 fortify.c
字号:
/* * 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 * */#include <stdio.h>#include <stdlib.h>#include <malloc.h>#if defined FORTIFY#if defined MSDOS || defined __BORLANDC__ || defined WIN32 || defined __HIGHC__# include <direct.h>#endifextern int EndOfPgr();#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"#endifstruct 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__# define _static static#else# define _static#endif_static char *address __OF((void *));_static int TimeToCheck __OF((void));_static int CheckBlock __OF((struct Header *h, 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 WIN32static 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)); }#endifstatic char *address(addr) 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_CheckIntervalint TimeToCheck(){ static unsigned long lastcheck=0L; time_t t; int ret = 0; time(&t); if ((lastcheck==0L) || (t-lastcheck>=FORTIFY_CheckInterval)) { lastcheck = t; ret = 1; } return(ret);}#endifstatic FILE *gfile=NULL;static int Nchars=0,Nlines=0;static char flag=0;static void _Fortify_NoOutput() { }static void st_DefaultOutput(String) 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]=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 = 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=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+=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(file,line) 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,file,line) 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -