Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

521 lines
13 KiB

  1. /* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
  2. /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
  3. #include "precomp.h"
  4. #ifdef _DEBUG
  5. void MyDebugBreak(void)
  6. {
  7. // to correct the misleading stack dump
  8. DebugBreak();
  9. }
  10. #endif // _DEBUG
  11. // Memory manager for decoder
  12. #ifdef ENABLE_MEMORY_TRACKING
  13. LPVOID DbgDecMemAlloc ( ASN1decoding_t dec, ASN1uint32_t cbSize, LPSTR pszFileName, ASN1uint32_t nLineNumber )
  14. #else
  15. LPVOID DecMemAlloc ( ASN1decoding_t dec, ASN1uint32_t cbSize )
  16. #endif
  17. {
  18. LPVOID lp = NULL;
  19. ASN1INTERNdecoding_t lpInfo = (ASN1INTERNdecoding_t) dec;
  20. // make sure the size is 4-byte aligned
  21. ASN1_SIZE_ALIGNED(cbSize);
  22. // accumulate the total size
  23. lpInfo->cbLinearBufSize += cbSize;
  24. // allocate the buffer
  25. if (lpInfo->fExtBuf)
  26. {
  27. if (lpInfo->cbRemExtBufSize >= cbSize)
  28. {
  29. lp = lpInfo->lpRemExtBuf;
  30. lpInfo->lpRemExtBuf += cbSize;
  31. lpInfo->cbRemExtBufSize -= cbSize;
  32. }
  33. else
  34. {
  35. DecAssert(dec, FALSE);
  36. }
  37. }
  38. else
  39. {
  40. #ifdef ENABLE_MEMORY_TRACKING
  41. lp = DbgMemAlloc(cbSize, _ModName(dec), pszFileName, nLineNumber);
  42. #else
  43. lp = MemAllocEx(dec, cbSize, TRUE); // zero memory
  44. #endif
  45. }
  46. // make sure to propagate error
  47. if (lp == NULL)
  48. {
  49. ASN1DecSetError(dec, ASN1_ERR_MEMORY);
  50. }
  51. return lp;
  52. }
  53. void DecMemFree ( ASN1decoding_t dec, LPVOID lpData )
  54. {
  55. if (! ((ASN1INTERNdecoding_t) dec)->fExtBuf)
  56. {
  57. MemFree(lpData);
  58. }
  59. }
  60. #ifdef ENABLE_MEMORY_TRACKING
  61. LPVOID DbgDecMemReAlloc ( ASN1decoding_t dec, LPVOID lpData, ASN1uint32_t cbSize, LPSTR pszFileName, ASN1uint32_t nLineNumber )
  62. #else
  63. LPVOID DecMemReAlloc ( ASN1decoding_t dec, LPVOID lpData, ASN1uint32_t cbSize )
  64. #endif
  65. {
  66. LPVOID lp = NULL;
  67. // make sure the size is 4-byte aligned
  68. ASN1_SIZE_ALIGNED(cbSize);
  69. // accumulate the total size
  70. ((ASN1INTERNdecoding_t) dec)->cbLinearBufSize += cbSize;
  71. // allocate the buffer
  72. if (((ASN1INTERNdecoding_t) dec)->fExtBuf)
  73. {
  74. if (lpData == NULL)
  75. {
  76. lp = DecMemAlloc(dec, cbSize);
  77. }
  78. else
  79. {
  80. DecAssert(dec, FALSE);
  81. }
  82. }
  83. else
  84. {
  85. #ifdef ENABLE_MEMORY_TRACKING
  86. lp = DbgMemReAlloc(lpData, cbSize, _ModName(dec), pszFileName, nLineNumber);
  87. #else
  88. lp = MemReAllocEx(dec, lpData, cbSize, TRUE); // zero memory
  89. #endif
  90. }
  91. // make sure to propagate error
  92. if (lp == NULL)
  93. {
  94. ASN1DecSetError(dec, ASN1_ERR_MEMORY);
  95. }
  96. return lp;
  97. }
  98. /***
  99. *char *ms_bSearch() - do a binary search on an array
  100. *
  101. *Purpose:
  102. * Does a binary search of a sorted array for a key.
  103. *
  104. *Entry:
  105. * const char *key - key to search for
  106. * const char *base - base of sorted array to search
  107. * unsigned int num - number of elements in array
  108. * unsigned int width - number of bytes per element
  109. * int (*compare)() - pointer to function that compares two array
  110. * elements, returning neg when #1 < #2, pos when #1 > #2, and
  111. * 0 when they are equal. Function is passed pointers to two
  112. * array elements.
  113. *
  114. *Exit:
  115. * if key is found:
  116. * returns pointer to occurrence of key in array
  117. * if key is not found:
  118. * returns NULL
  119. *
  120. *Exceptions:
  121. *
  122. *******************************************************************************/
  123. void * ms_bSearch (
  124. const void *key,
  125. const void *base,
  126. size_t num,
  127. size_t width,
  128. int (__cdecl *compare)(const void *, const void *)
  129. )
  130. {
  131. char *lo = (char *)base;
  132. char *hi = (char *)base + (num - 1) * width;
  133. char *mid;
  134. unsigned int half;
  135. int result;
  136. while (lo <= hi)
  137. if (half = num / 2)
  138. {
  139. mid = lo + (num & 1 ? half : (half - 1)) * width;
  140. if (!(result = (*compare)(key,mid)))
  141. return(mid);
  142. else if (result < 0)
  143. {
  144. hi = mid - width;
  145. num = num & 1 ? half : half-1;
  146. }
  147. else {
  148. lo = mid + width;
  149. num = half;
  150. }
  151. }
  152. else if (num)
  153. return((*compare)(key,lo) ? NULL : lo);
  154. else
  155. break;
  156. return(NULL);
  157. }
  158. int IsDigit(char p)
  159. {
  160. return ((p >= ('0')) && (p <=('9'))) ? 1 : 0 ;
  161. }
  162. // BUGBUG - This is a copy of the same routine in nmutil
  163. // BUGBUG - Remove this when we convert our files to CPP and use nmutil
  164. /* D E C I M A L S T R I N G T O U I N T */
  165. /*-------------------------------------------------------------------------
  166. %%Function: DecimalStringToUINT
  167. -------------------------------------------------------------------------*/
  168. unsigned int DecimalStringToUINT(char * pcszString, ASN1uint32_t cch)
  169. {
  170. unsigned int uRet = 0;
  171. char * pszStr = pcszString;
  172. while (cch-- && ('\0') != pszStr[0])
  173. {
  174. uRet = (10 * uRet) + (int) (pszStr[0] - ('0'));
  175. pszStr++; // NOTE: DBCS characters are not allowed!
  176. }
  177. return uRet;
  178. }
  179. #ifdef ENABLE_BER
  180. int My_memcmp(ASN1octet_t *pBuf1, ASN1uint32_t cbBuf1Size, ASN1octet_t *pBuf2, ASN1uint32_t cbBuf2Size)
  181. {
  182. int diff;
  183. ASN1uint32_t cbMinBufSize = (cbBuf1Size < cbBuf2Size) ? cbBuf1Size : cbBuf2Size;
  184. while (cbMinBufSize--)
  185. {
  186. diff = (int) (ASN1uint32_t) *pBuf1++ - (int) (ASN1uint32_t) *pBuf2++;
  187. if (0 != diff)
  188. {
  189. return diff;
  190. }
  191. }
  192. return ((int) cbBuf1Size - (int) cbBuf2Size);
  193. }
  194. #endif // ENABLE_BER
  195. // THE FOLLOWING IS FROM ILS.DLL MEMORY TRACKING
  196. #ifdef ENABLE_MEMORY_TRACKING
  197. #ifndef _DEBUG
  198. void MyDebugBreak(void)
  199. {
  200. // to correct the misleading stack dump
  201. DebugBreak();
  202. }
  203. #endif // _DEBUG
  204. #define KEEP_FREE_MEM
  205. #define DBG_NAME_LENGTH 16
  206. typedef struct tagMemTag
  207. {
  208. DWORD dwSignature;
  209. BOOL fActive;
  210. ASN1uint32_t nModuleName;
  211. CHAR szFileName[DBG_NAME_LENGTH];
  212. UINT nLineNumber;
  213. UINT cbSize;
  214. struct tagMemTag *next;
  215. }
  216. MEM_TAG;
  217. static MEM_TAG *s_pDbgActiveMemPool = NULL;
  218. #ifdef KEEP_FREE_MEM
  219. static MEM_TAG *s_pDbgFreeMemPool = NULL;
  220. #define FREE_BYTE ((BYTE) 0xAB)
  221. #define TAIL_BYTE ((BYTE) 0xEF)
  222. #define TAIL_SIZE 8
  223. #endif
  224. #define CLEAN_BYTE ((BYTE) 0xCD)
  225. static UINT s_cDbgActiveMemAlloc = 0;
  226. static UINT s_cbDbgActiveMem = 0;
  227. const DWORD MEM_TAG_SIGNATURE = 0x12345678UL;
  228. static BOOL s_fDbgInitCritSect = FALSE;
  229. static CRITICAL_SECTION s_DbgCritSect;
  230. void DbgMemTrackReverseList(void)
  231. {
  232. EnterCriticalSection(&s_DbgCritSect);
  233. if (NULL != s_pDbgActiveMemPool && NULL != s_pDbgActiveMemPool->next)
  234. {
  235. MEM_TAG *p, *q, *r;;
  236. for (q = (p = s_pDbgActiveMemPool)->next, r = q; // make sure r is not null in the beginning
  237. NULL != r;
  238. p = q, q = r)
  239. {
  240. r = q->next;
  241. q->next = p;
  242. }
  243. s_pDbgActiveMemPool->next = NULL;
  244. s_pDbgActiveMemPool = p;
  245. }
  246. LeaveCriticalSection(&s_DbgCritSect);
  247. }
  248. #define DBG_MEM_TRACK_DUMP_ALL ((ASN1uint32_t) -1)
  249. void ASN1DbgMemTrackDumpCurrent ( ASN1uint32_t nModuleName )
  250. {
  251. MEM_TAG *p;
  252. int i;
  253. char szMod[8];
  254. char szBuf[128];
  255. EnterCriticalSection(&s_DbgCritSect);
  256. for (p = s_pDbgActiveMemPool, i = 0; p; p = p->next, i++)
  257. {
  258. if (nModuleName == DBG_MEM_TRACK_DUMP_ALL || p->nModuleName == nModuleName)
  259. {
  260. ZeroMemory(szMod, sizeof(szMod));
  261. CopyMemory(szMod, &p->nModuleName, sizeof(ASN1uint32_t));
  262. wsprintfA(szBuf, "ASN1: mem leak [%u]: mod=%s, file=%s, line=%u, size=%u, ptr=0x%lx\r\n",
  263. i, szMod, p->szFileName, p->nLineNumber, p->cbSize, (ASN1uint32_t) (p+1));
  264. OutputDebugStringA(szBuf);
  265. }
  266. }
  267. LeaveCriticalSection(&s_DbgCritSect);
  268. }
  269. void DbgMemTrackFinalCheck ( void )
  270. {
  271. DbgMemTrackReverseList();
  272. ASN1DbgMemTrackDumpCurrent(DBG_MEM_TRACK_DUMP_ALL);
  273. if (NULL != s_pDbgActiveMemPool ||
  274. 0 != s_cDbgActiveMemAlloc ||
  275. 0 != s_cbDbgActiveMem)
  276. {
  277. MyDebugBreak();
  278. }
  279. if (s_fDbgInitCritSect)
  280. {
  281. DeleteCriticalSection(&s_DbgCritSect);
  282. s_fDbgInitCritSect = FALSE;
  283. }
  284. }
  285. static void _GetFileName ( LPSTR pszTarget, LPSTR pszSrc )
  286. {
  287. LPSTR psz = pszSrc;
  288. while (*psz != '\0')
  289. {
  290. if (*psz++ == '\\')
  291. {
  292. pszSrc = psz;
  293. }
  294. }
  295. lstrcpynA(pszTarget, pszSrc, DBG_NAME_LENGTH);
  296. }
  297. static BOOL _IsFilledMemory ( LPBYTE lpb, UINT cbSize, BYTE bPattern )
  298. {
  299. while (cbSize--)
  300. {
  301. if (*lpb++ != bPattern)
  302. return FALSE;
  303. }
  304. return TRUE;
  305. }
  306. LPVOID DbgMemAlloc ( UINT cbSize, ASN1uint32_t nModuleName, LPSTR pszFileName, UINT nLineNumber )
  307. {
  308. MEM_TAG *p;
  309. UINT cbToAlloc;
  310. if (! s_fDbgInitCritSect)
  311. {
  312. InitializeCriticalSection(&s_DbgCritSect);
  313. s_fDbgInitCritSect = TRUE;
  314. }
  315. cbToAlloc = sizeof(MEM_TAG) + cbSize;
  316. EnterCriticalSection(&s_DbgCritSect);
  317. #ifdef KEEP_FREE_MEM
  318. // add the tail size
  319. cbToAlloc += TAIL_SIZE;
  320. // any heap corruption in free pool
  321. {
  322. const int c_cKept = 32;
  323. MEM_TAG *q = s_pDbgFreeMemPool;
  324. int i;
  325. for (i = 0; i < c_cKept; i++)
  326. {
  327. if (q == NULL)
  328. break;
  329. if (! _IsFilledMemory((LPBYTE) (q+1), q->cbSize, FREE_BYTE))
  330. {
  331. MyDebugBreak();
  332. }
  333. if (! _IsFilledMemory(((LPBYTE) (q+1)) + q->cbSize, TAIL_SIZE, TAIL_BYTE))
  334. {
  335. MyDebugBreak();
  336. }
  337. if (c_cKept == i)
  338. {
  339. MEM_TAG *x = q->next, *y;
  340. q->next = NULL;
  341. while (x)
  342. {
  343. y = x->next;
  344. LocalFree(x);
  345. x = y;
  346. }
  347. break;
  348. }
  349. q = q->next;
  350. }
  351. }
  352. #endif
  353. p = (MEM_TAG *) LocalAlloc(LPTR, cbToAlloc);
  354. if (p != NULL)
  355. {
  356. p->dwSignature = MEM_TAG_SIGNATURE;
  357. p->nModuleName = nModuleName;
  358. p->fActive = TRUE;
  359. _GetFileName(p->szFileName, pszFileName);
  360. p->nLineNumber = nLineNumber;
  361. p->cbSize = cbSize;
  362. p->next = s_pDbgActiveMemPool;
  363. s_pDbgActiveMemPool = p;
  364. s_cDbgActiveMemAlloc++;
  365. s_cbDbgActiveMem += p->cbSize;
  366. #ifdef KEEP_FREE_MEM
  367. FillMemory((LPVOID) ((LPBYTE) (p+1) + p->cbSize), TAIL_SIZE, TAIL_BYTE);
  368. #endif
  369. p++;
  370. // lonchanc; do not fill in some garbage, we must provide same semantics
  371. // for decoded buffers. all zeroed out.
  372. // fill in some garbage
  373. // FillMemory((LPVOID) p, cbSize, CLEAN_BYTE);
  374. }
  375. LeaveCriticalSection(&s_DbgCritSect);
  376. return (LPVOID) p;
  377. }
  378. void DbgMemFree ( LPVOID ptr )
  379. {
  380. if (ptr != NULL)
  381. {
  382. MEM_TAG *p = (MEM_TAG *) ptr;
  383. MEM_TAG *q, *q0;
  384. p--;
  385. if (! IsBadWritePtr(p, sizeof(MEM_TAG)) &&
  386. p->dwSignature == MEM_TAG_SIGNATURE)
  387. {
  388. if (! p->fActive)
  389. {
  390. //
  391. // This memory has been freed already.
  392. //
  393. MyDebugBreak();
  394. return;
  395. }
  396. EnterCriticalSection(&s_DbgCritSect);
  397. for (q = s_pDbgActiveMemPool; q != NULL; q = (q0 = q)->next)
  398. {
  399. if (q == p)
  400. {
  401. if (q == s_pDbgActiveMemPool)
  402. {
  403. s_pDbgActiveMemPool = p->next;
  404. }
  405. else
  406. {
  407. q0->next = p->next;
  408. }
  409. s_cDbgActiveMemAlloc--;
  410. s_cbDbgActiveMem -= p->cbSize;
  411. p->fActive = FALSE;
  412. if (! _IsFilledMemory(((LPBYTE) (p+1)) + p->cbSize, TAIL_SIZE, TAIL_BYTE))
  413. {
  414. MyDebugBreak();
  415. }
  416. #ifdef KEEP_FREE_MEM
  417. // put in the free pool
  418. p->next = s_pDbgFreeMemPool;
  419. s_pDbgFreeMemPool = p;
  420. FillMemory(p+1, p->cbSize, FREE_BYTE);
  421. #endif
  422. break;
  423. }
  424. }
  425. LeaveCriticalSection(&s_DbgCritSect);
  426. }
  427. else
  428. {
  429. p++;
  430. MyDebugBreak();
  431. }
  432. #ifndef KEEP_FREE_MEM
  433. LocalFree(p);
  434. #endif
  435. }
  436. }
  437. LPVOID DbgMemReAlloc ( LPVOID ptr, UINT cbSize, ASN1uint32_t nModuleName, LPSTR pszFileName, UINT nLineNumber )
  438. {
  439. MEM_TAG *p;
  440. void *q;
  441. if (ptr == NULL)
  442. return DbgMemAlloc(cbSize, nModuleName, pszFileName, nLineNumber);
  443. p = (MEM_TAG *) ptr;
  444. p--;
  445. if (IsBadWritePtr(p, sizeof(MEM_TAG)) ||
  446. p->dwSignature != MEM_TAG_SIGNATURE)
  447. {
  448. MyDebugBreak();
  449. return LocalReAlloc(ptr, cbSize, LMEM_MOVEABLE|LMEM_ZEROINIT);
  450. }
  451. q = DbgMemAlloc(cbSize, nModuleName, pszFileName, nLineNumber);
  452. if (q != NULL)
  453. {
  454. CopyMemory(q, ptr, p->cbSize);
  455. DbgMemFree(ptr);
  456. }
  457. return q;
  458. }
  459. #endif // ENABLE_MEMORY_TRACKING