|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
heap.c
Abstract:
This module implements verification functions for heap management interfaces.
Author:
Silviu Calinoiu (SilviuC) 7-Mar-2001
Revision History:
--*/
#include "pch.h"
#include "verifier.h"
#include "support.h"
#include "critsect.h"
#include "faults.h"
//
// During manipulation of DPH_BLOCK_INFORMATION we get this because
// pointers have a default 8 byte aligned. However they will always
// be 16-byte aligned because they are derived from heap allocated
// blocks and these are 16 byte aligned anyway.
//
#if defined(_WIN64)
#pragma warning(disable:4327)
#endif
//
// Dirty unused portions of stack in order to catch usage of
// uninitialized locals.
//
#define AVRFP_DIRTY_STACK_FREQUENCY 16
LONG AVrfpDirtyStackCounter;
#define AVRFP_DIRTY_THREAD_STACK() { \
if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_DIRTY_STACKS) != 0) { \ if ((InterlockedIncrement(&AVrfpDirtyStackCounter) % AVRFP_DIRTY_STACK_FREQUENCY) == 0) { \ AVrfpDirtyThreadStack (); \ } \ } \ }
//
// Simple test to figure out if a heap was created by page heap or it is
// just a normal heap.
//
#define IS_PAGE_HEAP(HeapHandle) (*(PULONG)HeapHandle == 0xEEEEEEEE)
#define RAISE_NO_MEMORY_EXCEPTION() \
{ \ EXCEPTION_RECORD ER; \ ER.ExceptionCode = STATUS_NO_MEMORY; \ ER.ExceptionFlags = 0; \ ER.ExceptionRecord = NULL; \ ER.ExceptionAddress = _ReturnAddress(); \ ER.NumberParameters = 0; \ RtlRaiseException( &ER ); \ }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//NTSYSAPI
PVOID NTAPI AVrfpRtlAllocateHeap( IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size ) { PVOID Result;
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); if ((Flags & HEAP_GENERATE_EXCEPTIONS)) { RAISE_NO_MEMORY_EXCEPTION (); }
return NULL; }
Result = RtlAllocateHeap (HeapHandle, Flags, Size);
if (Result) {
AVrfLogInTracker (AVrfHeapTracker, TRACK_HEAP_ALLOCATE, Result, (PVOID)Size, NULL, NULL, _ReturnAddress()); }
AVRFP_DIRTY_THREAD_STACK ();
return Result; }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//NTSYSAPI
BOOLEAN NTAPI AVrfpRtlFreeHeap( IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress ) { BOOLEAN Result; BOOL BogusAddress; SIZE_T RequestedSize; PDPH_BLOCK_INFORMATION BlockInformation;
//
// Initialize RequestedSize in order to be able to compile W4.
// The variable gets actually initialized when it matters but
// the compiler is not able to realize that. If while initializing
// it we get an exception then we will not use it.
//
RequestedSize = 0;
if (BaseAddress != NULL && IS_PAGE_HEAP (HeapHandle)) {
BogusAddress = FALSE;
BlockInformation = (PDPH_BLOCK_INFORMATION)BaseAddress - 1;
try {
RequestedSize = BlockInformation->RequestedSize; } except (EXCEPTION_EXECUTE_HANDLER) {
//
// Let page heap handle the bogus block.
//
BogusAddress = TRUE; }
if (BogusAddress == FALSE) {
AVrfpFreeMemNotify (VerifierFreeMemTypeFreeHeap, BaseAddress, RequestedSize, NULL); } }
Result = RtlFreeHeap (HeapHandle, Flags, BaseAddress);
if (Result) { AVrfLogInTracker (AVrfHeapTracker, TRACK_HEAP_FREE, BaseAddress, NULL, NULL, NULL, _ReturnAddress()); }
AVRFP_DIRTY_THREAD_STACK ();
return Result; }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//NTSYSAPI
PVOID NTAPI AVrfpRtlReAllocateHeap( IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN SIZE_T Size ) { PVOID Result; BOOL BogusAddress; SIZE_T RequestedSize; PDPH_BLOCK_INFORMATION BlockInformation;
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); if ((Flags & HEAP_GENERATE_EXCEPTIONS)) { RAISE_NO_MEMORY_EXCEPTION (); }
return NULL; } //
// Initialize RequestedSize in order to be able to compile W4.
// The variable gets actually initialized when it matters but
// the compiler is not able to realize that. If while initializing
// it we get an exception then we will not use it.
//
RequestedSize = 0; if (BaseAddress != NULL && IS_PAGE_HEAP (HeapHandle) && ((Flags & HEAP_REALLOC_IN_PLACE_ONLY) != 0)) {
BogusAddress = FALSE;
BlockInformation = (PDPH_BLOCK_INFORMATION)BaseAddress - 1;
try {
RequestedSize = BlockInformation->RequestedSize; } except (EXCEPTION_EXECUTE_HANDLER) { //
// Let page heap handle the bogus block.
//
BogusAddress = TRUE; }
if (BogusAddress == FALSE) {
AVrfpFreeMemNotify (VerifierFreeMemTypeFreeHeap, BaseAddress, RequestedSize, NULL); } }
Result = RtlReAllocateHeap (HeapHandle, Flags, BaseAddress, Size);
if (Result) { AVrfLogInTracker (AVrfHeapTracker, TRACK_HEAP_REALLOCATE, BaseAddress, Result, (PVOID)Size, NULL, _ReturnAddress()); }
AVRFP_DIRTY_THREAD_STACK ();
return Result; }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
VOID AVrfpNtdllHeapFreeCallback ( PVOID AllocationBase, SIZE_T AllocationSize ) { AVrfpFreeMemNotify (VerifierFreeMemTypeFreeHeap, AllocationBase, AllocationSize, NULL); }
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////// kernel32.dll verified exports
/////////////////////////////////////////////////////////////////////
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
HANDLE WINAPI AVrfpHeapCreate( IN DWORD flOptions, IN SIZE_T dwInitialSize, IN SIZE_T dwMaximumSize ) { typedef HANDLE (WINAPI * FUNCTION_TYPE) (DWORD, SIZE_T, SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_HEAPCREATE);
BUMP_COUNTER (CNT_HEAPS_CREATED); return (* Function)(flOptions, dwInitialSize, dwMaximumSize); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
BOOL WINAPI AVrfpHeapDestroy( IN OUT HANDLE hHeap ) { typedef BOOL (WINAPI * FUNCTION_TYPE) (HANDLE); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_HEAPDESTROY);
BUMP_COUNTER (CNT_HEAPS_DESTROYED); return (* Function)(hHeap); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
HGLOBAL WINAPI AVrfpGlobalAlloc( IN UINT uFlags, IN SIZE_T dwBytes ) { typedef HGLOBAL (WINAPI * FUNCTION_TYPE) (UINT, SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_GLOBALALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return NULL; } return (* Function)(uFlags, dwBytes); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
HGLOBAL WINAPI AVrfpGlobalReAlloc( IN HGLOBAL hMem, IN SIZE_T dwBytes, IN UINT uFlags ) { typedef HGLOBAL (WINAPI * FUNCTION_TYPE) (HGLOBAL, SIZE_T, UINT); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_GLOBALREALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return NULL; } return (* Function)(hMem, dwBytes, uFlags); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
HLOCAL WINAPI AVrfpLocalAlloc( IN UINT uFlags, IN SIZE_T uBytes ) { typedef HLOCAL (WINAPI * FUNCTION_TYPE) (UINT, SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_LOCALALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return NULL; } return (* Function)(uFlags, uBytes); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
//WINBASEAPI
HLOCAL WINAPI AVrfpLocalReAlloc( IN HLOCAL hMem, IN SIZE_T uBytes, IN UINT uFlags ) { typedef HLOCAL (WINAPI * FUNCTION_TYPE) (HLOCAL, SIZE_T, UINT); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_LOCALREALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return NULL; } return (* Function)(hMem, uBytes, uFlags); }
/////////////////////////////////////////////////////////////////////
////////////////////////////////////////// msvcrt allocation routines
/////////////////////////////////////////////////////////////////////
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
PVOID __cdecl AVrfp_malloc ( IN SIZE_T Size ) { typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_MALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); return NULL; } return (* Function)(Size); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
PVOID __cdecl AVrfp_calloc ( IN SIZE_T Number, IN SIZE_T Size ) { typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T, SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_CALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); return NULL; } return (* Function)(Number, Size); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
PVOID __cdecl AVrfp_realloc ( IN PVOID Address, IN SIZE_T Size ) { typedef PVOID (__cdecl * FUNCTION_TYPE) (PVOID, SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_REALLOC);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); return NULL; } return (* Function)(Address, Size); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
VOID __cdecl AVrfp_free ( IN PVOID Address ) { typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_FREE);
(* Function)(Address); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
PVOID __cdecl AVrfp_new ( IN SIZE_T Size ) { typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_NEW);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); return NULL; } return (* Function)(Size); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
VOID __cdecl AVrfp_delete ( IN PVOID Address ) { typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_DELETE);
(* Function)(Address); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
PVOID __cdecl AVrfp_newarray ( IN SIZE_T Size ) { typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_NEWARRAY);
BUMP_COUNTER (CNT_HEAP_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_HEAP_ALLOC_APIS)) { BUMP_COUNTER (CNT_HEAP_ALLOC_FAILS); CHECK_BREAK (BRK_HEAP_ALLOC_FAIL); return NULL; } return (* Function)(Size); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
VOID __cdecl AVrfp_deletearray ( IN PVOID Address ) { typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks, AVRF_INDEX_MSVCRT_DELETEARRAY);
(* Function)(Address); }
/////////////////////////////////////////////////////////////////////
/////////////////////////////////// oleaut32 BSTR allocation routines
/////////////////////////////////////////////////////////////////////
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
BSTR STDAPICALLTYPE AVrfpSysAllocString(const OLECHAR * String) { typedef BSTR (STDAPICALLTYPE * FUNCTION_TYPE) (const OLECHAR *); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpOleaut32Thunks, AVRF_INDEX_OLEAUT32_SYSALLOCSTRING);
BUMP_COUNTER (CNT_OLE_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_OLE_ALLOC_APIS)) { BUMP_COUNTER (CNT_OLE_ALLOC_FAILS); CHECK_BREAK (BRK_OLE_ALLOC_FAIL); return NULL; } return (* Function)(String); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
INT STDAPICALLTYPE AVrfpSysReAllocString(BSTR * BStr, const OLECHAR *String) { typedef INT (STDAPICALLTYPE * FUNCTION_TYPE) (BSTR *, const OLECHAR *); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpOleaut32Thunks, AVRF_INDEX_OLEAUT32_SYSREALLOCSTRING);
BUMP_COUNTER (CNT_OLE_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_OLE_ALLOC_APIS)) { BUMP_COUNTER (CNT_OLE_ALLOC_FAILS); CHECK_BREAK (BRK_OLE_ALLOC_FAIL); return FALSE; } return (* Function)(BStr, String); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
BSTR STDAPICALLTYPE AVrfpSysAllocStringLen(const OLECHAR *String, UINT Length) { typedef BSTR (STDAPICALLTYPE * FUNCTION_TYPE) (const OLECHAR *, UINT); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpOleaut32Thunks, AVRF_INDEX_OLEAUT32_SYSALLOCSTRINGLEN);
BUMP_COUNTER (CNT_OLE_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_OLE_ALLOC_APIS)) { BUMP_COUNTER (CNT_OLE_ALLOC_FAILS); CHECK_BREAK (BRK_OLE_ALLOC_FAIL); return NULL; } return (* Function)(String, Length); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
INT STDAPICALLTYPE AVrfpSysReAllocStringLen(BSTR * BStr, const OLECHAR * String, UINT Length) { typedef INT (STDAPICALLTYPE * FUNCTION_TYPE) (BSTR *, const OLECHAR *, UINT); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpOleaut32Thunks, AVRF_INDEX_OLEAUT32_SYSREALLOCSTRINGLEN);
BUMP_COUNTER (CNT_OLE_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_OLE_ALLOC_APIS)) { BUMP_COUNTER (CNT_OLE_ALLOC_FAILS); CHECK_BREAK (BRK_OLE_ALLOC_FAIL); return FALSE; } return (* Function)(BStr, String, Length); }
#if defined(_X86_)
#pragma optimize("y", off) // disable FPO
#endif
BSTR STDAPICALLTYPE AVrfpSysAllocStringByteLen(LPCSTR psz, UINT len) { typedef BSTR (STDAPICALLTYPE * FUNCTION_TYPE) (LPCSTR, UINT); FUNCTION_TYPE Function;
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpOleaut32Thunks, AVRF_INDEX_OLEAUT32_SYSALLOCSTRINGBYTELEN);
BUMP_COUNTER (CNT_OLE_ALLOC_CALLS); if (SHOULD_FAULT_INJECT(CLS_OLE_ALLOC_APIS)) { BUMP_COUNTER (CNT_OLE_ALLOC_FAILS); CHECK_BREAK (BRK_OLE_ALLOC_FAIL); return NULL; } return (* Function)(psz, len); }
|