📄 fortify.c
字号:
FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + size,
FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
#ifdef FORTIFY_FILL_ON_ALLOCATE
/*
* Fill the actual user memory
*/
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
FORTIFY_FILL_ON_ALLOCATE_VALUE, size);
#endif
/*
* End Critical Region
*/
FORTIFY_UNLOCK();
/*
* update the statistics
*/
st_TotalAllocation += size;
st_Allocations++;
st_CurBlocks++;
st_CurAllocation += size;
if (st_CurBlocks > st_MaxBlocks)
st_MaxBlocks = st_CurBlocks;
if (st_CurAllocation > st_MaxAllocation)
st_MaxAllocation = st_CurAllocation;
/*
* We return the address of the user's memory, not the start of the block,
* which points to our magic cookies
*/
return (ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE);
}
/*
* Fortify_Deallocate() - Free a block of memory allocated with Fortify_Allocate()
*/
void FORTIFY_STORAGE
Fortify_Deallocate(void *uptr, BYTE deallocator, const char *file, DWORD line)
{
BYTE *ptr = (BYTE *)uptr
- FORTIFY_HEADER_SIZE
- FORTIFY_ALIGNED_BEFORE_SIZE;
struct Header *h = (struct Header *)ptr;
#ifdef FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE
Fortify_CheckAllMemory(file, line);
#endif
/*
* If Fortify has been disabled, then it's easy
* (well, almost)
*/
if (st_Disabled)
{
/* there is a possibility that this memory
* block was allocated when Fortify was
* enabled, so we must check the Allocated
* list before we free it.
*/
if (!st_IsOnAllocatedList(h))
{
free(uptr);
return;
}
else
{
/* the block was allocated by Fortify, so we
* gotta free it differently.
*/
/*
* Begin critical region
*/
FORTIFY_LOCK();
/*
* Remove the block from the list
*/
if (h->Prev)
h->Prev->Next = h->Next;
else
st_AllocatedHead = h->Next;
if (h->Next)
h->Next->Prev = h->Prev;
/*
* End Critical Region
*/
FORTIFY_UNLOCK();
/*
* actually free the memory
*/
free(ptr);
return;
}
}
#ifdef FORTIFY_PARANOID_DEALLOCATE
if (!st_IsOnAllocatedList(h))
{
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
if (st_IsOnDeallocatedList(h))
{
sprintf(st_Buffer, "\nFortify: \"%s\" twice of %s detected at %s.%lu\n",
st_DeallocatorName[deallocator],
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_OutputDeleteTrace();
return;
}
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
sprintf (st_Buffer, "\nFortify: Possible \"%s\" twice of (%08lX) was detected at %s.%lu\n",
st_DeallocatorName[deallocator], (DWORD)uptr, file, line);
st_Output(st_Buffer);
st_OutputDeleteTrace();
return;
}
#endif /* FORTIFY_PARANOID_DELETE */
/*
* Make sure the block is okay before we free it.
* If it's not okay, don't free it - it might not
* be a real memory block. Or worse still, someone
* might still be writing to it
*/
if (!st_CheckBlock(h, file, line))
{
st_OutputDeleteTrace();
return;
}
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
/*
* Make sure the block hasn't been freed already
* (we can get to here if FORTIFY_PARANOID_DELETE
* is off, but FORTIFY_TRACK_DEALLOCATED_MEMORY
* is on).
*/
if (h->Deallocator != Fortify_Deallocator_nobody)
{
sprintf(st_Buffer, "\nFortify: \"%s\" twice of %s detected at %s.%lu\n",
st_DeallocatorName[deallocator],
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_OutputDeleteTrace();
return;
}
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
/*
* Make sure the block is being freed with a valid
* deallocator. If not, complain. (but free it anyway)
*/
if ((st_ValidDeallocator[h->Allocator] & (1 << deallocator)) == 0)
{
sprintf(st_Buffer, "\nFortify: Incorrect deallocator \"%s\" detected at %s.%lu\n",
st_DeallocatorName[deallocator], file, line);
st_Output(st_Buffer);
sprintf(st_Buffer, " %s was allocated with \"%s\"\n",
st_MemoryBlockString(h), st_AllocatorName[h->Allocator]);
st_Output(st_Buffer);
st_OutputDeleteTrace();
}
/*
* Begin critical region
*/
FORTIFY_LOCK();
/*
* Remove the block from the list
*/
if (h->Prev)
{
if (!st_CheckBlock(h->Prev, file, line))
{
FORTIFY_UNLOCK();
st_OutputDeleteTrace();
return;
}
h->Prev->Next = h->Next;
st_MakeHeaderValid(h->Prev);
}
else
st_AllocatedHead = h->Next;
if (h->Next)
{
if (!st_CheckBlock(h->Next, file, line))
{
FORTIFY_UNLOCK();
st_OutputDeleteTrace();
return;
}
h->Next->Prev = h->Prev;
st_MakeHeaderValid(h->Next);
}
/*
* End Critical Region
*/
FORTIFY_UNLOCK();
/*
* update the statistics
*/
st_Frees++;
st_CurBlocks--;
st_CurAllocation -= h->Size;
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
if (st_Scope > 0)
{
/*
* Don't _actually_ free the memory block, just yet.
* Place it onto the deallocated list, instead, so
* we can check later to see if it's been written to.
*/
#ifdef FORTIFY_FILL_ON_DEALLOCATE
/*
* Nuke out all user memory that is about to be freed
*/
st_SetFortification(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
FORTIFY_FILL_ON_DEALLOCATE_VALUE,
h->Size);
#endif /* FORTIFY_FILL_ON_DEALLOCATE */
/*
* Begin critical region
*/
FORTIFY_LOCK();
/*
* Place the block on the deallocated list
*/
if (st_DeallocatedHead)
{
st_DeallocatedHead->Prev = (struct Header *)ptr;
st_MakeHeaderValid(st_DeallocatedHead);
}
h = (struct Header *)ptr;
h->FreedFile = file;
h->FreedLine = line;
h->Deallocator = deallocator;
h->Next = st_DeallocatedHead;
h->Prev = 0;
st_MakeHeaderValid(h);
st_DeallocatedHead = h;
if (!st_DeallocatedTail)
{
st_DeallocatedTail = h;
}
st_TotalDeallocated += h->Size;
#ifdef FORTIFY_DEALLOCATED_MEMORY_LIMIT
/*
* If we've got too much on the deallocated list; free some
*/
if (st_TotalDeallocated > FORTIFY_DEALLOCATED_MEMORY_LIMIT)
{
st_PurgeDeallocatedBlocks(st_TotalDeallocated - FORTIFY_DEALLOCATED_MEMORY_LIMIT, file, line);
}
#endif
/*
* End critical region
*/
FORTIFY_UNLOCK();
}
else
#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
{
/*
* Free the User Label
*/
if (h->Label)
{
free(h->Label);
}
#ifdef FORTIFY_FILL_ON_DEALLOCATE
/*
* Nuke out all memory that is about to be freed, including the header
*/
st_SetFortification(ptr, FORTIFY_FILL_ON_DEALLOCATE_VALUE,
FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + h->Size + FORTIFY_AFTER_SIZE);
#endif /* FORTIFY_FILL_ON_DEALLOCATE */
/*
* And do the actual free
*/
free(ptr);
}
}
/*
* Fortify_LabelPointer() - Labels the memory block
* with a string provided by the user. This function
* takes a copy of the passed in string.
* The pointer MUST be one returned by a Fortify
* allocation function.
*/
/*@-redef@*/
void
Fortify_LabelPointer(void *uptr, const char *label, const char *file, DWORD line)
{
if (!st_Disabled)
{
BYTE *ptr = (BYTE *)uptr
- FORTIFY_HEADER_SIZE - FORTIFY_ALIGNED_BEFORE_SIZE;
struct Header *h = (struct Header *)ptr;
/* make sure the pointer is okay */
Fortify_CheckPointer(uptr, file, line);
/* free the previous label */
if (h->Label)
{
free(h->Label);
}
/* make sure the label is sensible */
assert(label);
/* copy it in */
h->Label = (char*)malloc(strlen(label)+1);
strcpy(h->Label, label);
/* update the checksum */
st_MakeHeaderValid(h);
}
}
/*
* Fortify_CheckPointer() - Returns true if the uptr
* points to a valid piece of Fortify_Allocated()'d
* memory. The memory must be on the allocated list,
* and it's fortifications must be intact.
* Always returns TRUE if Fortify is disabled.
*/
int FORTIFY_STORAGE
Fortify_CheckPointer(void *uptr, const char *file, DWORD line)
{
BYTE *ptr = (BYTE *)uptr
- FORTIFY_HEADER_SIZE - FORTIFY_ALIGNED_BEFORE_SIZE;
struct Header *h = (struct Header *)ptr;
int r;
if (st_Disabled)
return 1;
FORTIFY_LOCK();
if (!st_IsOnAllocatedList(h))
{
sprintf (st_Buffer, "\nFortify: Invalid pointer (%08lX) detected at %s.%lu\n",
(DWORD) uptr, file, line);
st_Output(st_Buffer);
FORTIFY_UNLOCK();
return (0);
}
#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
if (st_IsOnDeallocatedList(h))
{
sprintf (st_Buffer, "\nFortify: Deallocated pointer (%08lX) detected at %s.%lu\n",
(DWORD) uptr, 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);
FORTIFY_UNLOCK();
return (0);
}
#endif
r = st_CheckBlock(h, file, line);
FORTIFY_UNLOCK();
return r;
}
/*
* Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) -
* Sets the function used to output all error and
* diagnostic messages. The output function takes
* a single const BYTE * argument, and must be
* able to handle newlines. This function returns the
* old output function.
*/
Fortify_OutputFuncPtr FORTIFY_STORAGE
Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output)
{
Fortify_OutputFuncPtr Old = st_Output;
st_Output = Output;
return (Old);
}
/*
* Fortify_SetAllocateFailRate(int Percent) -
* Fortify_Allocate() will "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 (a good default I think).
*/
int FORTIFY_STORAGE
Fortify_SetAllocateFailRate(int Percent)
{
int Old = st_AllocateFailRate;
st_AllocateFailRate = Percent;
return (Old);
}
/*
* Fortify_CheckAllMemory() - Checks the fortifications
* of all memory on the allocated list. And, if
* FORTIFY_DEALLOCATED_MEMORY is enabled, all the
* known deallocated memory as well.
* Returns the number of blocks that failed.
* Always returns 0 if Fortify is disabled.
*/
DWORD FORTIFY_STORAGE
Fortify_CheckAllMemory(const char *file, DWORD line)
{
struct Header *curr = st_AllocatedHead;
DWORD count = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -