Skip to content

Commit

Permalink
eliminates possible deadlock related to memory allocation on global h…
Browse files Browse the repository at this point in the history
…eap (microsoft#70)
  • Loading branch information
adams85 committed Apr 12, 2022
1 parent 3326512 commit e683a04
Show file tree
Hide file tree
Showing 6 changed files with 2,382 additions and 2,235 deletions.
12 changes: 7 additions & 5 deletions src/creatwth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
goto Cleanup;
}

rlpDlls = new NOTHROW LPCSTR [s_pHelper->nDlls];
rlpDlls = DetourAllocArray<LPCSTR>(s_pHelper->nDlls);
cSize = s_pHelper->cb - sizeof(DETOUR_EXE_HELPER);
for (DWORD n = 0; n < s_pHelper->nDlls; n++) {
size_t cchDest = 0;
Expand All @@ -1177,7 +1177,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,

Cleanup:
if (rlpDlls != NULL) {
delete[] rlpDlls;
DetourFreeArray(rlpDlls);
rlpDlls = NULL;
}

Expand Down Expand Up @@ -1251,7 +1251,7 @@ BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper,
cSize += (DWORD)cchDest + 1;
}

Helper = (PDETOUR_EXE_HELPER) new NOTHROW BYTE[sizeof(DETOUR_EXE_HELPER) + cSize];
Helper = (PDETOUR_EXE_HELPER)DetourAllocArray<BYTE>(sizeof(DETOUR_EXE_HELPER) + cSize);
if (Helper == NULL) {
goto Cleanup;
}
Expand Down Expand Up @@ -1316,7 +1316,8 @@ BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper,

Cleanup:
if (Helper != NULL) {
delete[] (PBYTE)Helper;
PBYTE helperBytes = (PBYTE)Helper;
DetourFreeArray(helperBytes);
Helper = NULL;
}
return Result;
Expand All @@ -1326,7 +1327,8 @@ static
VOID WINAPI FreeExeHelper(PDETOUR_EXE_HELPER *pHelper)
{
if (*pHelper != NULL) {
delete[] (PBYTE)*pHelper;
PBYTE helperBytes = (PBYTE)*pHelper;
DetourFreeArray(helperBytes);
*pHelper = NULL;
}
}
Expand Down
63 changes: 53 additions & 10 deletions src/detours.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#define DETOURS_INTERNAL
#include "detours.h"

#include <new.h>

#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
Expand Down Expand Up @@ -1628,7 +1630,7 @@ LONG WINAPI DetourTransactionAbort()
}

DetourOperation *n = o->pNext;
delete o;
DetourFree(o);
o = n;
}
s_pPendingOperations = NULL;
Expand All @@ -1642,7 +1644,7 @@ LONG WINAPI DetourTransactionAbort()
ResumeThread(t->hThread);

DetourThread *n = t->pNext;
delete t;
DetourFree(t);
t = n;
}
s_pPendingThreads = NULL;
Expand Down Expand Up @@ -1913,7 +1915,7 @@ typedef ULONG_PTR DETOURS_EIP_TYPE;
}

DetourOperation *n = o->pNext;
delete o;
DetourFree(o);
o = n;
}
s_pPendingOperations = NULL;
Expand All @@ -1932,7 +1934,7 @@ typedef ULONG_PTR DETOURS_EIP_TYPE;
ResumeThread(t->hThread);

DetourThread *n = t->pNext;
delete t;
DetourFree(t);
t = n;
}
s_pPendingThreads = NULL;
Expand All @@ -1959,12 +1961,12 @@ LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread)
return NO_ERROR;
}

DetourThread *t = new NOTHROW DetourThread;
DetourThread *t = DetourAlloc<DetourThread>();
if (t == NULL) {
error = ERROR_NOT_ENOUGH_MEMORY;
fail:
if (t != NULL) {
delete t;
DetourFree(t);
t = NULL;
}
s_nPendingError = error;
Expand Down Expand Up @@ -2080,7 +2082,7 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
*ppRealDetour = pDetour;
}

o = new NOTHROW DetourOperation;
o = DetourAlloc<DetourOperation>();
if (o == NULL) {
error = ERROR_NOT_ENOUGH_MEMORY;
fail:
Expand All @@ -2095,7 +2097,7 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
}
}
if (o != NULL) {
delete o;
DetourFree(o);
o = NULL;
}
if (ppRealDetour != NULL) {
Expand Down Expand Up @@ -2382,15 +2384,15 @@ LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer,
return error;
}

DetourOperation *o = new NOTHROW DetourOperation;
DetourOperation *o = DetourAlloc<DetourOperation>();
if (o == NULL) {
error = ERROR_NOT_ENOUGH_MEMORY;
fail:
s_nPendingError = error;
DETOUR_BREAK();
stop:
if (o != NULL) {
delete o;
DetourFree(o);
o = NULL;
}
s_ppPendingError = ppPointer;
Expand Down Expand Up @@ -2594,4 +2596,45 @@ BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right)
left.Data4[7] == right.Data4[7];
}

//////////////////////////////////////////////////////////////////////////////
//

static HANDLE s_hHeap = NULL;

void DetourDestroyHeap()
{
if (s_hHeap)
{
HeapDestroy(s_hHeap);
s_hHeap = NULL;
}
}

BOOL DetourCreateHeap(BOOL fAutoDestroy)
{
BOOL bResult = FALSE;
if (s_hHeap == NULL)
{
s_hHeap = HeapCreate(0, 0, 0);
assert(s_hHeap);
if (s_hHeap != NULL)
{
if (fAutoDestroy)
{
atexit(DetourDestroyHeap);
}
bResult = TRUE;
}
}
return bResult;
}

inline HANDLE DetourGetHeap()
{
assert(s_hHeap);
return s_hHeap;
}

static BOOL s_fAlreadyCreatedDetourHeap = DetourCreateHeap(TRUE);

// End of File
103 changes: 103 additions & 0 deletions src/detours.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include <intsafe.h>
#pragma warning(pop)
#endif
#include <assert.h>
#include <crtdbg.h>

// Allow Detours to cleanly compile with the MingW toolchain.
Expand Down Expand Up @@ -1213,6 +1214,108 @@ BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right);
}
#endif // __cplusplus

//////////////////////////////////////////////////////////// Memory management APIs.

inline HANDLE DetourGetHeap();

template<class T>
T* DetourAlloc()
{
void* p = HeapAlloc(DetourGetHeap(), 0, sizeof(T));
assert(p);
if (!p)
{
return NULL;
}

return ::new(p) T;
}

template<class T, class P1>
T* DetourAlloc(P1 p1)
{
void* p = HeapAlloc(DetourGetHeap(), 0, sizeof(T));
assert(p);
if (!p)
{
return NULL;
}

return ::new(p) T(p1);
}

template<class T, class P1, class P2>
T* DetourAlloc(P1 p1, P2 p2)
{
void* p = HeapAlloc(DetourGetHeap(), 0, sizeof(T));
assert(p);
if (!p)
{
return NULL;
}

return ::new(p) T(p1, p2);
}

template<class T>
void DetourFree(T*& p)
{
size_t MemSize = HeapSize(DetourGetHeap(), 0, p);
assert(MemSize == sizeof(T));
if (MemSize != sizeof(T))
{
return;
}

p->~T();

HeapFree(DetourGetHeap(), 0, p);
p = NULL;
}

template<class T>
T* DetourAllocArray(size_t _Size)
{
T* p = (T*)HeapAlloc(DetourGetHeap(), 0, sizeof(T) * _Size);
assert(p);
if (!p)
{
return NULL;
}

for (size_t i = 0; i < _Size; i++)
{
::new(&p[i]) T;
}

return p;
}

template<class T>
void DetourFreeArray(T*& p)
{
size_t MemSize = HeapSize(DetourGetHeap(), 0, p);
assert(MemSize > 0);
if (MemSize == 0)
{
return;
}
size_t _Size = MemSize / sizeof(T);
assert(_Size > 0);
if (_Size == 0)
{
return;
}

for (size_t i = 0; i < _Size; i++)
{
(&p[i])->~T();
}

HeapFree(DetourGetHeap(), 0, (LPVOID)p);
p = NULL;
}

//////////////////////////////////////////////////////////////////////////////

#define MM_ALLOCATION_GRANULARITY 0x10000
Expand Down
Loading

0 comments on commit e683a04

Please sign in to comment.