|
|
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#ifdef _DEBUG
void MyDebugBreak(void) { // to correct the misleading stack dump
DebugBreak(); } #endif // _DEBUG
// Memory manager for decoder
#ifdef ENABLE_MEMORY_TRACKING
LPVOID DbgDecMemAlloc ( ASN1decoding_t dec, ASN1uint32_t cbSize, LPSTR pszFileName, ASN1uint32_t nLineNumber ) #else
LPVOID DecMemAlloc ( ASN1decoding_t dec, ASN1uint32_t cbSize ) #endif
{ LPVOID lp = NULL; ASN1INTERNdecoding_t lpInfo = (ASN1INTERNdecoding_t) dec; // make sure the size is 4-byte aligned
ASN1_SIZE_ALIGNED(cbSize); // accumulate the total size
lpInfo->cbLinearBufSize += cbSize; // allocate the buffer
if (lpInfo->fExtBuf) { if (lpInfo->cbRemExtBufSize >= cbSize) { lp = lpInfo->lpRemExtBuf; lpInfo->lpRemExtBuf += cbSize; lpInfo->cbRemExtBufSize -= cbSize; } else { DecAssert(dec, FALSE); } } else { #ifdef ENABLE_MEMORY_TRACKING
lp = DbgMemAlloc(cbSize, _ModName(dec), pszFileName, nLineNumber); #else
lp = MemAllocEx(dec, cbSize, TRUE); // zero memory
#endif
} // make sure to propagate error
if (lp == NULL) { ASN1DecSetError(dec, ASN1_ERR_MEMORY); } return lp; }
void DecMemFree ( ASN1decoding_t dec, LPVOID lpData ) { if (! ((ASN1INTERNdecoding_t) dec)->fExtBuf) { MemFree(lpData); } }
#ifdef ENABLE_MEMORY_TRACKING
LPVOID DbgDecMemReAlloc ( ASN1decoding_t dec, LPVOID lpData, ASN1uint32_t cbSize, LPSTR pszFileName, ASN1uint32_t nLineNumber ) #else
LPVOID DecMemReAlloc ( ASN1decoding_t dec, LPVOID lpData, ASN1uint32_t cbSize ) #endif
{ LPVOID lp = NULL; // make sure the size is 4-byte aligned
ASN1_SIZE_ALIGNED(cbSize); // accumulate the total size
((ASN1INTERNdecoding_t) dec)->cbLinearBufSize += cbSize; // allocate the buffer
if (((ASN1INTERNdecoding_t) dec)->fExtBuf) { if (lpData == NULL) { lp = DecMemAlloc(dec, cbSize); } else { DecAssert(dec, FALSE); } } else { #ifdef ENABLE_MEMORY_TRACKING
lp = DbgMemReAlloc(lpData, cbSize, _ModName(dec), pszFileName, nLineNumber); #else
lp = MemReAllocEx(dec, lpData, cbSize, TRUE); // zero memory
#endif
} // make sure to propagate error
if (lp == NULL) { ASN1DecSetError(dec, ASN1_ERR_MEMORY); } return lp; }
/***
*char *ms_bSearch() - do a binary search on an array * *Purpose: * Does a binary search of a sorted array for a key. * *Entry: * const char *key - key to search for * const char *base - base of sorted array to search * unsigned int num - number of elements in array * unsigned int width - number of bytes per element * int (*compare)() - pointer to function that compares two array * elements, returning neg when #1 < #2, pos when #1 > #2, and * 0 when they are equal. Function is passed pointers to two * array elements. * *Exit: * if key is found: * returns pointer to occurrence of key in array * if key is not found: * returns NULL * *Exceptions: * *******************************************************************************/
void * ms_bSearch ( const void *key, const void *base, size_t num, size_t width, int (__cdecl *compare)(const void *, const void *) ) { char *lo = (char *)base; char *hi = (char *)base + (num - 1) * width; char *mid; unsigned int half; int result;
while (lo <= hi) if (half = num / 2) { mid = lo + (num & 1 ? half : (half - 1)) * width; if (!(result = (*compare)(key,mid))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } else if (num) return((*compare)(key,lo) ? NULL : lo); else break;
return(NULL); }
int IsDigit(char p) { return ((p >= ('0')) && (p <=('9'))) ? 1 : 0 ; }
// BUGBUG - This is a copy of the same routine in nmutil
// BUGBUG - Remove this when we convert our files to CPP and use nmutil
/* D E C I M A L S T R I N G T O U I N T */ /*-------------------------------------------------------------------------
%%Function: DecimalStringToUINT -------------------------------------------------------------------------*/ unsigned int DecimalStringToUINT(char * pcszString, ASN1uint32_t cch) { unsigned int uRet = 0; char * pszStr = pcszString; while (cch-- && ('\0') != pszStr[0]) { uRet = (10 * uRet) + (int) (pszStr[0] - ('0')); pszStr++; // NOTE: DBCS characters are not allowed!
} return uRet; }
#ifdef ENABLE_BER
int My_memcmp(ASN1octet_t *pBuf1, ASN1uint32_t cbBuf1Size, ASN1octet_t *pBuf2, ASN1uint32_t cbBuf2Size) { int diff; ASN1uint32_t cbMinBufSize = (cbBuf1Size < cbBuf2Size) ? cbBuf1Size : cbBuf2Size; while (cbMinBufSize--) { diff = (int) (ASN1uint32_t) *pBuf1++ - (int) (ASN1uint32_t) *pBuf2++; if (0 != diff) { return diff; } } return ((int) cbBuf1Size - (int) cbBuf2Size); } #endif // ENABLE_BER
// THE FOLLOWING IS FROM ILS.DLL MEMORY TRACKING
#ifdef ENABLE_MEMORY_TRACKING
#ifndef _DEBUG
void MyDebugBreak(void) { // to correct the misleading stack dump
DebugBreak(); } #endif // _DEBUG
#define KEEP_FREE_MEM
#define DBG_NAME_LENGTH 16
typedef struct tagMemTag { DWORD dwSignature; BOOL fActive; ASN1uint32_t nModuleName; CHAR szFileName[DBG_NAME_LENGTH]; UINT nLineNumber; UINT cbSize; struct tagMemTag *next; } MEM_TAG;
static MEM_TAG *s_pDbgActiveMemPool = NULL; #ifdef KEEP_FREE_MEM
static MEM_TAG *s_pDbgFreeMemPool = NULL; #define FREE_BYTE ((BYTE) 0xAB)
#define TAIL_BYTE ((BYTE) 0xEF)
#define TAIL_SIZE 8
#endif
#define CLEAN_BYTE ((BYTE) 0xCD)
static UINT s_cDbgActiveMemAlloc = 0; static UINT s_cbDbgActiveMem = 0; const DWORD MEM_TAG_SIGNATURE = 0x12345678UL;
static BOOL s_fDbgInitCritSect = FALSE; static CRITICAL_SECTION s_DbgCritSect;
void DbgMemTrackReverseList(void) { EnterCriticalSection(&s_DbgCritSect); if (NULL != s_pDbgActiveMemPool && NULL != s_pDbgActiveMemPool->next) { MEM_TAG *p, *q, *r;;
for (q = (p = s_pDbgActiveMemPool)->next, r = q; // make sure r is not null in the beginning
NULL != r; p = q, q = r) { r = q->next; q->next = p; }
s_pDbgActiveMemPool->next = NULL; s_pDbgActiveMemPool = p; } LeaveCriticalSection(&s_DbgCritSect); }
#define DBG_MEM_TRACK_DUMP_ALL ((ASN1uint32_t) -1)
void ASN1DbgMemTrackDumpCurrent ( ASN1uint32_t nModuleName ) { MEM_TAG *p; int i; char szMod[8]; char szBuf[128]; EnterCriticalSection(&s_DbgCritSect); for (p = s_pDbgActiveMemPool, i = 0; p; p = p->next, i++) { if (nModuleName == DBG_MEM_TRACK_DUMP_ALL || p->nModuleName == nModuleName) { ZeroMemory(szMod, sizeof(szMod)); CopyMemory(szMod, &p->nModuleName, sizeof(ASN1uint32_t)); wsprintfA(szBuf, "ASN1: mem leak [%u]: mod=%s, file=%s, line=%u, size=%u, ptr=0x%lx\r\n", i, szMod, p->szFileName, p->nLineNumber, p->cbSize, (ASN1uint32_t) (p+1)); OutputDebugStringA(szBuf); } } LeaveCriticalSection(&s_DbgCritSect); }
void DbgMemTrackFinalCheck ( void ) { DbgMemTrackReverseList(); ASN1DbgMemTrackDumpCurrent(DBG_MEM_TRACK_DUMP_ALL); if (NULL != s_pDbgActiveMemPool || 0 != s_cDbgActiveMemAlloc || 0 != s_cbDbgActiveMem) { MyDebugBreak(); }
if (s_fDbgInitCritSect) { DeleteCriticalSection(&s_DbgCritSect); s_fDbgInitCritSect = FALSE; } }
static void _GetFileName ( LPSTR pszTarget, LPSTR pszSrc ) { LPSTR psz = pszSrc; while (*psz != '\0') { if (*psz++ == '\\') { pszSrc = psz; } } lstrcpynA(pszTarget, pszSrc, DBG_NAME_LENGTH); }
static BOOL _IsFilledMemory ( LPBYTE lpb, UINT cbSize, BYTE bPattern ) { while (cbSize--) { if (*lpb++ != bPattern) return FALSE; } return TRUE; }
LPVOID DbgMemAlloc ( UINT cbSize, ASN1uint32_t nModuleName, LPSTR pszFileName, UINT nLineNumber ) { MEM_TAG *p; UINT cbToAlloc;
if (! s_fDbgInitCritSect) { InitializeCriticalSection(&s_DbgCritSect); s_fDbgInitCritSect = TRUE; }
cbToAlloc = sizeof(MEM_TAG) + cbSize;
EnterCriticalSection(&s_DbgCritSect);
#ifdef KEEP_FREE_MEM
// add the tail size
cbToAlloc += TAIL_SIZE;
// any heap corruption in free pool
{ const int c_cKept = 32; MEM_TAG *q = s_pDbgFreeMemPool; int i; for (i = 0; i < c_cKept; i++) { if (q == NULL) break;
if (! _IsFilledMemory((LPBYTE) (q+1), q->cbSize, FREE_BYTE)) { MyDebugBreak(); }
if (! _IsFilledMemory(((LPBYTE) (q+1)) + q->cbSize, TAIL_SIZE, TAIL_BYTE)) { MyDebugBreak(); }
if (c_cKept == i) { MEM_TAG *x = q->next, *y; q->next = NULL; while (x) { y = x->next; LocalFree(x); x = y; } break; }
q = q->next; } } #endif
p = (MEM_TAG *) LocalAlloc(LPTR, cbToAlloc); if (p != NULL) { p->dwSignature = MEM_TAG_SIGNATURE; p->nModuleName = nModuleName; p->fActive = TRUE; _GetFileName(p->szFileName, pszFileName); p->nLineNumber = nLineNumber; p->cbSize = cbSize; p->next = s_pDbgActiveMemPool; s_pDbgActiveMemPool = p; s_cDbgActiveMemAlloc++; s_cbDbgActiveMem += p->cbSize; #ifdef KEEP_FREE_MEM
FillMemory((LPVOID) ((LPBYTE) (p+1) + p->cbSize), TAIL_SIZE, TAIL_BYTE); #endif
p++;
// lonchanc; do not fill in some garbage, we must provide same semantics
// for decoded buffers. all zeroed out.
// fill in some garbage
// FillMemory((LPVOID) p, cbSize, CLEAN_BYTE);
}
LeaveCriticalSection(&s_DbgCritSect);
return (LPVOID) p; }
void DbgMemFree ( LPVOID ptr ) { if (ptr != NULL) { MEM_TAG *p = (MEM_TAG *) ptr; MEM_TAG *q, *q0; p--; if (! IsBadWritePtr(p, sizeof(MEM_TAG)) && p->dwSignature == MEM_TAG_SIGNATURE) { if (! p->fActive) { //
// This memory has been freed already.
//
MyDebugBreak(); return; }
EnterCriticalSection(&s_DbgCritSect); for (q = s_pDbgActiveMemPool; q != NULL; q = (q0 = q)->next) { if (q == p) { if (q == s_pDbgActiveMemPool) { s_pDbgActiveMemPool = p->next; } else { q0->next = p->next; } s_cDbgActiveMemAlloc--; s_cbDbgActiveMem -= p->cbSize; p->fActive = FALSE;
if (! _IsFilledMemory(((LPBYTE) (p+1)) + p->cbSize, TAIL_SIZE, TAIL_BYTE)) { MyDebugBreak(); } #ifdef KEEP_FREE_MEM
// put in the free pool
p->next = s_pDbgFreeMemPool; s_pDbgFreeMemPool = p; FillMemory(p+1, p->cbSize, FREE_BYTE); #endif
break; } } LeaveCriticalSection(&s_DbgCritSect); } else { p++; MyDebugBreak(); } #ifndef KEEP_FREE_MEM
LocalFree(p); #endif
} }
LPVOID DbgMemReAlloc ( LPVOID ptr, UINT cbSize, ASN1uint32_t nModuleName, LPSTR pszFileName, UINT nLineNumber ) { MEM_TAG *p; void *q;
if (ptr == NULL) return DbgMemAlloc(cbSize, nModuleName, pszFileName, nLineNumber);
p = (MEM_TAG *) ptr; p--;
if (IsBadWritePtr(p, sizeof(MEM_TAG)) || p->dwSignature != MEM_TAG_SIGNATURE) { MyDebugBreak(); return LocalReAlloc(ptr, cbSize, LMEM_MOVEABLE|LMEM_ZEROINIT); }
q = DbgMemAlloc(cbSize, nModuleName, pszFileName, nLineNumber); if (q != NULL) { CopyMemory(q, ptr, p->cbSize); DbgMemFree(ptr); }
return q; }
#endif // ENABLE_MEMORY_TRACKING
|