📄 fortify.c
字号:
{#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(uptr,file,line) void *uptr; char *file; unsigned long line;{ unsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; struct Header *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(ptr,new_size,file,line) void *ptr; size_t new_size; char *file; unsigned long line;{ void *new_ptr; struct Header *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). */int FORTIFY_STORAGE_Fortify_CheckPointer(uptr,file,line) void *uptr; char *file; unsigned long line;{ unsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; int r; stdOutput = 0; if(st_Disabled) { WaitIfstdOutput(); return(1); } FORTIFY_LOCK(); if(!IsOnList((struct Header *)ptr)) { 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); } r = CheckBlock((struct Header *)ptr, file, line); FORTIFY_UNLOCK(); WaitIfstdOutput(); return(r);}/* * 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(Output) 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(Percent) 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(file,line) 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(file,line) 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(file,line) char *file; unsigned long line;{ struct Header *curr = st_Head; int count = 0; unsigned long 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(file,line) char *file; unsigned long line;{ struct Header *curr = st_Head; int count = 0; unsigned long 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(scope,file,line) int scope; char *file; unsigned long line;{ struct Header *curr = st_Head; int count = 0; unsigned long size = 0; stdOutput = 0; if(st_Disabled) { WaitIfstdOutput(); return(0); } FORTIFY_LOCK(); while(curr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -