📄 fortify.c
字号:
if (st_Disabled)
return 0;
FORTIFY_LOCK();
/*
* Check the allocated memory
*/
while (curr)
{
if (!st_CheckBlock(curr, file, line))
{
count++;
break; // !! added, GV 13/7-98
}
curr = curr->Next;
}
/*
* Check the deallocated memory while you're at it
*/
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
curr = st_DeallocatedHead;
while (curr)
{
if (!st_CheckDeallocatedBlock(curr, file, line))
count++;
curr = curr->Next;
}
#endif
/*
* If we know where we are, and everything is cool,
* remember that. It might be important.
*/
if (file && count == 0)
{
st_LastVerifiedFile = file;
st_LastVerifiedLine = line;
}
FORTIFY_UNLOCK();
return (count);
}
/*
* Fortify_EnterScope() - enters a new Fortify scope
* level. Returns the new scope level.
*/
BYTE FORTIFY_STORAGE
Fortify_EnterScope(const char *file, DWORD line)
{
ARGSUSED (file);
ARGSUSED (line);
return (++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.
* Does nothing and returns 0 if Fortify is disabled.
*/
BYTE FORTIFY_STORAGE
Fortify_LeaveScope(const char *file, DWORD line)
{
struct Header *curr = st_AllocatedHead;
DWORD size = 0, count = 0;
if (st_Disabled)
return 0;
FORTIFY_LOCK();
st_Scope--;
while (curr)
{
if (curr->Scope > st_Scope)
{
if (count == 0)
{
sprintf(st_Buffer, "\nFortify: Memory leak detected leaving scope at %s.%lu\n", file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, "%10s %8s %s\n", "Address", "Size", "Allocator");
st_Output(st_Buffer);
}
st_OutputHeader(curr);
count++;
size += curr->Size;
}
curr = curr->Next;
}
if (count)
{
sprintf(st_Buffer,"%8s %8lu bytes in %lu blocks with %lu bytes overhead\n",
"total", size, count, count * FORTIFY_OVERHEAD);
st_Output(st_Buffer);
}
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
/*
* Quietly free all the deallocated memory
* that was allocated in this scope that
* we are still tracking
*/
st_PurgeDeallocatedScope (st_Scope, file, line);
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
FORTIFY_UNLOCK();
return (st_Scope);
}
/*
* Fortify_ListAllMemory() - Outputs the entire
* list of currently allocated memory. For each 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.
*/
DWORD FORTIFY_STORAGE
Fortify_ListAllMemory(const char *file, DWORD line)
{
struct Header *curr = st_AllocatedHead;
DWORD size = 0, count = 0;
if (st_Disabled)
return 0;
Fortify_CheckAllMemory(file, line);
FORTIFY_LOCK();
if (curr)
{
sprintf(st_Buffer, "\n\nFortify: Memory List at %s.%lu\n", file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, "%10s %8s %s\n", "Address", "Size", "Allocator");
st_Output(st_Buffer);
while (curr)
{
st_OutputHeader(curr);
count++;
size += curr->Size;
curr = curr->Next;
}
sprintf(st_Buffer, "%8s %8lu bytes in %lu blocks and %lu bytes overhead\n",
"total", size, count, count * FORTIFY_OVERHEAD);
st_Output(st_Buffer);
}
FORTIFY_UNLOCK();
return (count);
}
/*
* Fortify_DumpAllMemory() - Outputs the entire list of
* currently allocated memory. For each allocated 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.
*/
DWORD FORTIFY_STORAGE
Fortify_DumpAllMemory(const char *file, DWORD line)
{
struct Header *curr = st_AllocatedHead;
DWORD count = 0;
if (st_Disabled)
return 0;
Fortify_CheckAllMemory(file, line);
FORTIFY_LOCK();
while (curr)
{
sprintf(st_Buffer, "\nFortify: Hex Dump of %s at %s.%lu\n",
st_MemoryBlockString(curr), file, line);
st_Output(st_Buffer);
st_OutputMemory(curr);
st_Output("\n");
count++;
curr = curr->Next;
}
FORTIFY_UNLOCK();
return (count);
}
/* Fortify_OutputStatistics() - displays statistics
* about the maximum amount of memory that was
* allocated at any one time.
*/
void FORTIFY_STORAGE
Fortify_OutputStatistics(const char *file, DWORD line)
{
if (st_Disabled)
return;
sprintf(st_Buffer, "\nFortify: Statistics at %s.%lu\n", file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, " Memory currently allocated: %lu bytes in %lu blocks\n",
st_CurAllocation, st_CurBlocks);
st_Output(st_Buffer);
sprintf(st_Buffer, " Maximum memory allocated at one time: %lu bytes in %lu blocks\n",
st_MaxAllocation, st_MaxBlocks);
st_Output(st_Buffer);
sprintf(st_Buffer, " There have been %lu allocations and %lu deallocations\n",
st_Allocations, st_Frees);
st_Output(st_Buffer);
sprintf(st_Buffer, " There was a total of %lu bytes allocated\n",
st_TotalAllocation);
st_Output(st_Buffer);
if (st_Allocations > 0)
{
sprintf(st_Buffer, " The average allocation was %lu bytes\n",
st_TotalAllocation / st_Allocations);
st_Output(st_Buffer);
}
}
/* Fortify_GetCurrentAllocation() - returns the number of
* bytes currently allocated.
*/
DWORD FORTIFY_STORAGE
Fortify_GetCurrentAllocation(const char *file, DWORD line)
{
ARGSUSED (file);
ARGSUSED (line);
if (st_Disabled)
return 0;
return st_CurAllocation;
}
/* Fortify_SetAllocationLimit() - set a limit on the total
* amount of memory allowed for this application.
*/
void FORTIFY_STORAGE
Fortify_SetAllocationLimit(DWORD NewLimit, const char *file, DWORD line)
{
ARGSUSED (file);
ARGSUSED (line);
st_AllocationLimit = NewLimit;
}
/*
* Fortify_Disable() - Run time method of disabling Fortify.
* Useful if you need to turn off Fortify without recompiling
* everything. Not as effective as compiling out, of course.
* The less memory allocated by Fortify when it is disabled
* the better.
* (Previous versions of Fortify did not allow it to be
* disabled if there was any memory allocated at the time,
* but since in C++ memory is often allocated before main
* is even entered, this was useless so Fortify is now
* able to cope).
*/
void FORTIFY_STORAGE
Fortify_Disable(const char *file, DWORD line)
{
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
/* free all deallocated memory we might be tracking */
st_PurgeDeallocatedScope (0, file, line);
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
st_Disabled = 1;
}
/*
* st_CheckBlock - Check a block's header and fortifications.
* Returns true if the block is happy.
*/
STATIC int
st_CheckBlock(struct Header *h, const char *file, DWORD line)
{
BYTE *ptr = (BYTE *)h;
int result = 1;
if (!st_IsHeaderValid(h))
{
sprintf (st_Buffer,
"\nFortify: Invalid pointer (%08lX) or corrupted header detected at %s.%lu\n",
(DWORD)(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE), file, line);
st_Output (st_Buffer);
st_OutputLastVerifiedPoint();
return (0);
}
if (!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE,
FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE))
{
sprintf(st_Buffer, "\nFortify: Underwrite detected before block %s at %s.%lu\n",
st_MemoryBlockString(h), file, line);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
st_OutputFortification(ptr + FORTIFY_HEADER_SIZE,
FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
result = 0;
#ifdef FORTIFY_FILL_ON_CORRUPTION
st_SetFortification(ptr + FORTIFY_HEADER_SIZE, FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
#endif
}
if (!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))
{
sprintf(st_Buffer, "\nFortify: Overwrite detected after block %s at %s.%lu\n",
st_MemoryBlockString(h), file, line);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
result = 0;
#ifdef FORTIFY_FILL_ON_CORRUPTION
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
#endif
}
return (result);
}
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
/*
* st_CheckDeallocatedBlock - Check a deallocated block's header and fortifications.
* Returns true if the block is happy.
*/
STATIC int
st_CheckDeallocatedBlock(struct Header *h, const char *file, DWORD line)
{
BYTE *ptr = (BYTE *)h;
int result = 1;
if (!st_IsHeaderValid(h))
{
sprintf (st_Buffer,
"\nFortify: Invalid deallocated pointer (%08lX) or corrupted header detected at %s.%lu\n",
(DWORD)(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE), file, line);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
return (0);
}
if (!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE,
FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE))
{
sprintf(st_Buffer, "\nFortify: Underwrite detected before deallocated block %s at %s.%lu\n",
st_MemoryBlockString(h), file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, " Memory block was deallocated by \"%s\" at %s.%lu\n",
st_DeallocatorName[h->Deallocator], h->FreedFile, h->FreedLine);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
st_OutputFortification(ptr + FORTIFY_HEADER_SIZE,
FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
#ifdef FORTIFY_FILL_ON_CORRUPTION
st_SetFortification(ptr + FORTIFY_HEADER_SIZE, FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
#endif
result = 0;
}
if (!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))
{
sprintf(st_Buffer, "\nFortify: Overwrite detected after deallocated block %s at %s.%lu\n",
st_MemoryBlockString(h), file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, " Memory block was deallocated by \"%s\" at %s.%lu\n",
st_DeallocatorName[h->Deallocator], h->FreedFile, h->FreedLine);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
#ifdef FORTIFY_FILL_ON_CORRUPTION
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
#endif
result = 0;
}
#ifdef FORTIFY_FILL_ON_DEALLOCATE
if (!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size))
{
sprintf(st_Buffer, "\nFortify: Write to deallocated block %s detected at %s.%lu\n",
st_MemoryBlockString(h), file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, " Memory block was deallocated by \"%s\" at %s.%lu\n",
st_DeallocatorName[h->Deallocator], h->FreedFile, h->FreedLine);
st_Output(st_Buffer);
st_OutputLastVerifiedPoint();
st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size);
#ifdef FORTIFY_FILL_ON_CORRUPTION
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size);
#endif /* FORTIFY_FILL_ON_CORRUPTION */
result = 0;
}
#endif /* FORTIFY_FILL_ON_DEALLOCATE */
return result;
}
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
/*
* st_CheckFortification - Checks if the _size_
* bytes from _ptr_ are all set to _value_
* Returns true if all is happy.
*/
STATIC int
st_CheckFortification(BYTE *ptr, BYTE value, size_t size)
{
while (size--)
if (*ptr++ != value)
return (0);
return (1);
}
/*
* st_SetFortification - Set the _size_ bytes from _ptr_ to _value_.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -