diff options
author | markus <> | 2002-09-05 12:51:50 +0000 |
---|---|---|
committer | markus <> | 2002-09-05 12:51:50 +0000 |
commit | 15b5d84f9da2ce4bfae8580e56e34a859f74ad71 (patch) | |
tree | bf939e82d7fd73cc8a01cf6959002209972091bc /src/lib/libcrypto/mem_dbg.c | |
parent | 027351f729b9e837200dae6e1520cda6577ab930 (diff) | |
download | openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.gz openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.bz2 openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.zip |
import openssl-0.9.7-beta1
Diffstat (limited to 'src/lib/libcrypto/mem_dbg.c')
-rw-r--r-- | src/lib/libcrypto/mem_dbg.c | 263 |
1 files changed, 167 insertions, 96 deletions
diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c index 14770c0733..1c4e04f51f 100644 --- a/src/lib/libcrypto/mem_dbg.c +++ b/src/lib/libcrypto/mem_dbg.c | |||
@@ -81,7 +81,8 @@ static int mh_mode=CRYPTO_MEM_CHECK_OFF; | |||
81 | */ | 81 | */ |
82 | 82 | ||
83 | static unsigned long order = 0; /* number of memory requests */ | 83 | static unsigned long order = 0; /* number of memory requests */ |
84 | static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */ | 84 | static LHASH *mh=NULL; /* hash-table of memory requests (address as key); |
85 | * access requires MALLOC2 lock */ | ||
85 | 86 | ||
86 | 87 | ||
87 | typedef struct app_mem_info_st | 88 | typedef struct app_mem_info_st |
@@ -103,12 +104,13 @@ typedef struct app_mem_info_st | |||
103 | 104 | ||
104 | static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's | 105 | static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's |
105 | * that are at the top of their thread's stack | 106 | * that are at the top of their thread's stack |
106 | * (with `thread' as key) */ | 107 | * (with `thread' as key); |
108 | * access requires MALLOC2 lock */ | ||
107 | 109 | ||
108 | typedef struct mem_st | 110 | typedef struct mem_st |
109 | /* memory-block description */ | 111 | /* memory-block description */ |
110 | { | 112 | { |
111 | char *addr; | 113 | void *addr; |
112 | int num; | 114 | int num; |
113 | const char *file; | 115 | const char *file; |
114 | int line; | 116 | int line; |
@@ -128,7 +130,15 @@ static long options = /* extra information to be recorded */ | |||
128 | 0; | 130 | 0; |
129 | 131 | ||
130 | 132 | ||
131 | static unsigned long disabling_thread = 0; | 133 | static unsigned int num_disable = 0; /* num_disable > 0 |
134 | * iff | ||
135 | * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) | ||
136 | */ | ||
137 | static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0. | ||
138 | * CRYPTO_LOCK_MALLOC2 is locked | ||
139 | * exactly in this case (by the | ||
140 | * thread named in disabling_thread). | ||
141 | */ | ||
132 | 142 | ||
133 | int CRYPTO_mem_ctrl(int mode) | 143 | int CRYPTO_mem_ctrl(int mode) |
134 | { | 144 | { |
@@ -137,22 +147,23 @@ int CRYPTO_mem_ctrl(int mode) | |||
137 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | 147 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
138 | switch (mode) | 148 | switch (mode) |
139 | { | 149 | { |
140 | /* for applications: */ | 150 | /* for applications (not to be called while multiple threads |
151 | * use the library): */ | ||
141 | case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ | 152 | case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ |
142 | mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; | 153 | mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; |
143 | disabling_thread = 0; | 154 | num_disable = 0; |
144 | break; | 155 | break; |
145 | case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ | 156 | case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ |
146 | mh_mode = 0; | 157 | mh_mode = 0; |
147 | disabling_thread = 0; | 158 | num_disable = 0; /* should be true *before* MemCheck_stop is used, |
159 | or there'll be a lot of confusion */ | ||
148 | break; | 160 | break; |
149 | 161 | ||
150 | /* switch off temporarily (for library-internal use): */ | 162 | /* switch off temporarily (for library-internal use): */ |
151 | case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ | 163 | case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ |
152 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | 164 | if (mh_mode & CRYPTO_MEM_CHECK_ON) |
153 | { | 165 | { |
154 | mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE; | 166 | if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */ |
155 | if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */ | ||
156 | { | 167 | { |
157 | /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while | 168 | /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while |
158 | * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if | 169 | * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if |
@@ -169,18 +180,23 @@ int CRYPTO_mem_ctrl(int mode) | |||
169 | * OpenSSL threads. */ | 180 | * OpenSSL threads. */ |
170 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | 181 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); |
171 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | 182 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
183 | mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; | ||
172 | disabling_thread=CRYPTO_thread_id(); | 184 | disabling_thread=CRYPTO_thread_id(); |
173 | } | 185 | } |
186 | num_disable++; | ||
174 | } | 187 | } |
175 | break; | 188 | break; |
176 | case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ | 189 | case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ |
177 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | 190 | if (mh_mode & CRYPTO_MEM_CHECK_ON) |
178 | { | 191 | { |
179 | mh_mode|=CRYPTO_MEM_CHECK_ENABLE; | 192 | if (num_disable) /* always true, or something is going wrong */ |
180 | if (disabling_thread != 0) | ||
181 | { | 193 | { |
182 | disabling_thread=0; | 194 | num_disable--; |
183 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | 195 | if (num_disable == 0) |
196 | { | ||
197 | mh_mode|=CRYPTO_MEM_CHECK_ENABLE; | ||
198 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | ||
199 | } | ||
184 | } | 200 | } |
185 | } | 201 | } |
186 | break; | 202 | break; |
@@ -198,12 +214,12 @@ int CRYPTO_is_mem_check_on(void) | |||
198 | 214 | ||
199 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | 215 | if (mh_mode & CRYPTO_MEM_CHECK_ON) |
200 | { | 216 | { |
201 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | 217 | CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); |
202 | 218 | ||
203 | ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) | 219 | ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) |
204 | && disabling_thread != CRYPTO_thread_id(); | 220 | || (disabling_thread != CRYPTO_thread_id()); |
205 | 221 | ||
206 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | 222 | CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); |
207 | } | 223 | } |
208 | return(ret); | 224 | return(ret); |
209 | } | 225 | } |
@@ -219,37 +235,43 @@ long CRYPTO_dbg_get_options(void) | |||
219 | return options; | 235 | return options; |
220 | } | 236 | } |
221 | 237 | ||
222 | static int mem_cmp(MEM *a, MEM *b) | 238 | /* static int mem_cmp(MEM *a, MEM *b) */ |
239 | static int mem_cmp(const void *a_void, const void *b_void) | ||
223 | { | 240 | { |
224 | return(a->addr - b->addr); | 241 | return((const char *)((const MEM *)a_void)->addr |
242 | - (const char *)((const MEM *)b_void)->addr); | ||
225 | } | 243 | } |
226 | 244 | ||
227 | static unsigned long mem_hash(MEM *a) | 245 | /* static unsigned long mem_hash(MEM *a) */ |
246 | static unsigned long mem_hash(const void *a_void) | ||
228 | { | 247 | { |
229 | unsigned long ret; | 248 | unsigned long ret; |
230 | 249 | ||
231 | ret=(unsigned long)a->addr; | 250 | ret=(unsigned long)((const MEM *)a_void)->addr; |
232 | 251 | ||
233 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; | 252 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; |
234 | return(ret); | 253 | return(ret); |
235 | } | 254 | } |
236 | 255 | ||
237 | static int app_info_cmp(APP_INFO *a, APP_INFO *b) | 256 | /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ |
257 | static int app_info_cmp(const void *a_void, const void *b_void) | ||
238 | { | 258 | { |
239 | return(a->thread != b->thread); | 259 | return(((const APP_INFO *)a_void)->thread |
260 | != ((const APP_INFO *)b_void)->thread); | ||
240 | } | 261 | } |
241 | 262 | ||
242 | static unsigned long app_info_hash(APP_INFO *a) | 263 | /* static unsigned long app_info_hash(APP_INFO *a) */ |
264 | static unsigned long app_info_hash(const void *a_void) | ||
243 | { | 265 | { |
244 | unsigned long ret; | 266 | unsigned long ret; |
245 | 267 | ||
246 | ret=(unsigned long)a->thread; | 268 | ret=(unsigned long)((const APP_INFO *)a_void)->thread; |
247 | 269 | ||
248 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; | 270 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; |
249 | return(ret); | 271 | return(ret); |
250 | } | 272 | } |
251 | 273 | ||
252 | static APP_INFO *pop_info() | 274 | static APP_INFO *pop_info(void) |
253 | { | 275 | { |
254 | APP_INFO tmp; | 276 | APP_INFO tmp; |
255 | APP_INFO *ret = NULL; | 277 | APP_INFO *ret = NULL; |
@@ -266,7 +288,7 @@ static APP_INFO *pop_info() | |||
266 | next->references++; | 288 | next->references++; |
267 | lh_insert(amih,(char *)next); | 289 | lh_insert(amih,(char *)next); |
268 | } | 290 | } |
269 | #ifdef LEVITTE_DEBUG | 291 | #ifdef LEVITTE_DEBUG_MEM |
270 | if (ret->thread != tmp.thread) | 292 | if (ret->thread != tmp.thread) |
271 | { | 293 | { |
272 | fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", | 294 | fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", |
@@ -279,7 +301,7 @@ static APP_INFO *pop_info() | |||
279 | ret->next = NULL; | 301 | ret->next = NULL; |
280 | if (next != NULL) | 302 | if (next != NULL) |
281 | next->references--; | 303 | next->references--; |
282 | Free(ret); | 304 | OPENSSL_free(ret); |
283 | } | 305 | } |
284 | } | 306 | } |
285 | } | 307 | } |
@@ -293,18 +315,18 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) | |||
293 | 315 | ||
294 | if (is_MemCheck_on()) | 316 | if (is_MemCheck_on()) |
295 | { | 317 | { |
296 | MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ | 318 | MemCheck_off(); /* obtain MALLOC2 lock */ |
297 | 319 | ||
298 | if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL) | 320 | if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) |
299 | { | 321 | { |
300 | ret=0; | 322 | ret=0; |
301 | goto err; | 323 | goto err; |
302 | } | 324 | } |
303 | if (amih == NULL) | 325 | if (amih == NULL) |
304 | { | 326 | { |
305 | if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL) | 327 | if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL) |
306 | { | 328 | { |
307 | Free(ami); | 329 | OPENSSL_free(ami); |
308 | ret=0; | 330 | ret=0; |
309 | goto err; | 331 | goto err; |
310 | } | 332 | } |
@@ -319,7 +341,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) | |||
319 | 341 | ||
320 | if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) | 342 | if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) |
321 | { | 343 | { |
322 | #ifdef LEVITTE_DEBUG | 344 | #ifdef LEVITTE_DEBUG_MEM |
323 | if (ami->thread != amim->thread) | 345 | if (ami->thread != amim->thread) |
324 | { | 346 | { |
325 | fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", | 347 | fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", |
@@ -330,7 +352,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) | |||
330 | ami->next=amim; | 352 | ami->next=amim; |
331 | } | 353 | } |
332 | err: | 354 | err: |
333 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 355 | MemCheck_on(); /* release MALLOC2 lock */ |
334 | } | 356 | } |
335 | 357 | ||
336 | return(ret); | 358 | return(ret); |
@@ -342,11 +364,11 @@ int CRYPTO_pop_info(void) | |||
342 | 364 | ||
343 | if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ | 365 | if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ |
344 | { | 366 | { |
345 | MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ | 367 | MemCheck_off(); /* obtain MALLOC2 lock */ |
346 | 368 | ||
347 | ret=(pop_info() != NULL); | 369 | ret=(pop_info() != NULL); |
348 | 370 | ||
349 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 371 | MemCheck_on(); /* release MALLOC2 lock */ |
350 | } | 372 | } |
351 | return(ret); | 373 | return(ret); |
352 | } | 374 | } |
@@ -357,12 +379,12 @@ int CRYPTO_remove_all_info(void) | |||
357 | 379 | ||
358 | if (is_MemCheck_on()) /* _must_ be true */ | 380 | if (is_MemCheck_on()) /* _must_ be true */ |
359 | { | 381 | { |
360 | MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ | 382 | MemCheck_off(); /* obtain MALLOC2 lock */ |
361 | 383 | ||
362 | while(pop_info() != NULL) | 384 | while(pop_info() != NULL) |
363 | ret++; | 385 | ret++; |
364 | 386 | ||
365 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 387 | MemCheck_on(); /* release MALLOC2 lock */ |
366 | } | 388 | } |
367 | return(ret); | 389 | return(ret); |
368 | } | 390 | } |
@@ -385,19 +407,20 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, | |||
385 | 407 | ||
386 | if (is_MemCheck_on()) | 408 | if (is_MemCheck_on()) |
387 | { | 409 | { |
388 | MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ | 410 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
389 | if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) | 411 | if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) |
390 | { | 412 | { |
391 | Free(addr); | 413 | OPENSSL_free(addr); |
392 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 414 | MemCheck_on(); /* release MALLOC2 lock |
415 | * if num_disabled drops to 0 */ | ||
393 | return; | 416 | return; |
394 | } | 417 | } |
395 | if (mh == NULL) | 418 | if (mh == NULL) |
396 | { | 419 | { |
397 | if ((mh=lh_new(mem_hash,mem_cmp)) == NULL) | 420 | if ((mh=lh_new(mem_hash, mem_cmp)) == NULL) |
398 | { | 421 | { |
399 | Free(addr); | 422 | OPENSSL_free(addr); |
400 | Free(m); | 423 | OPENSSL_free(m); |
401 | addr=NULL; | 424 | addr=NULL; |
402 | goto err; | 425 | goto err; |
403 | } | 426 | } |
@@ -418,8 +441,8 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, | |||
418 | m->order=order; | 441 | m->order=order; |
419 | } | 442 | } |
420 | m->order=order++; | 443 | m->order=order++; |
421 | #ifdef LEVITTE_DEBUG | 444 | #ifdef LEVITTE_DEBUG_MEM |
422 | fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n", | 445 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n", |
423 | m->order, | 446 | m->order, |
424 | (before_p & 128) ? '*' : '+', | 447 | (before_p & 128) ? '*' : '+', |
425 | m->addr, m->num); | 448 | m->addr, m->num); |
@@ -445,10 +468,11 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, | |||
445 | { | 468 | { |
446 | mm->app_info->references--; | 469 | mm->app_info->references--; |
447 | } | 470 | } |
448 | Free(mm); | 471 | OPENSSL_free(mm); |
449 | } | 472 | } |
450 | err: | 473 | err: |
451 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 474 | MemCheck_on(); /* release MALLOC2 lock |
475 | * if num_disabled drops to 0 */ | ||
452 | } | 476 | } |
453 | break; | 477 | break; |
454 | } | 478 | } |
@@ -467,24 +491,25 @@ void CRYPTO_dbg_free(void *addr, int before_p) | |||
467 | 491 | ||
468 | if (is_MemCheck_on() && (mh != NULL)) | 492 | if (is_MemCheck_on() && (mh != NULL)) |
469 | { | 493 | { |
470 | MemCheck_off(); | 494 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
471 | 495 | ||
472 | m.addr=addr; | 496 | m.addr=addr; |
473 | mp=(MEM *)lh_delete(mh,(char *)&m); | 497 | mp=(MEM *)lh_delete(mh,(char *)&m); |
474 | if (mp != NULL) | 498 | if (mp != NULL) |
475 | { | 499 | { |
476 | #ifdef LEVITTE_DEBUG | 500 | #ifdef LEVITTE_DEBUG_MEM |
477 | fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n", | 501 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n", |
478 | mp->order, mp->addr, mp->num); | 502 | mp->order, mp->addr, mp->num); |
479 | #endif | 503 | #endif |
480 | if (mp->app_info != NULL) | 504 | if (mp->app_info != NULL) |
481 | { | 505 | { |
482 | mp->app_info->references--; | 506 | mp->app_info->references--; |
483 | } | 507 | } |
484 | Free(mp); | 508 | OPENSSL_free(mp); |
485 | } | 509 | } |
486 | 510 | ||
487 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 511 | MemCheck_on(); /* release MALLOC2 lock |
512 | * if num_disabled drops to 0 */ | ||
488 | } | 513 | } |
489 | break; | 514 | break; |
490 | case 1: | 515 | case 1: |
@@ -497,8 +522,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, | |||
497 | { | 522 | { |
498 | MEM m,*mp; | 523 | MEM m,*mp; |
499 | 524 | ||
500 | #ifdef LEVITTE_DEBUG | 525 | #ifdef LEVITTE_DEBUG_MEM |
501 | fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", | 526 | fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", |
502 | addr1, addr2, num, file, line, before_p); | 527 | addr1, addr2, num, file, line, before_p); |
503 | #endif | 528 | #endif |
504 | 529 | ||
@@ -518,14 +543,14 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, | |||
518 | 543 | ||
519 | if (is_MemCheck_on()) | 544 | if (is_MemCheck_on()) |
520 | { | 545 | { |
521 | MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ | 546 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
522 | 547 | ||
523 | m.addr=addr1; | 548 | m.addr=addr1; |
524 | mp=(MEM *)lh_delete(mh,(char *)&m); | 549 | mp=(MEM *)lh_delete(mh,(char *)&m); |
525 | if (mp != NULL) | 550 | if (mp != NULL) |
526 | { | 551 | { |
527 | #ifdef LEVITTE_DEBUG | 552 | #ifdef LEVITTE_DEBUG_MEM |
528 | fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", | 553 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", |
529 | mp->order, | 554 | mp->order, |
530 | mp->addr, mp->num, | 555 | mp->addr, mp->num, |
531 | addr2, num); | 556 | addr2, num); |
@@ -535,7 +560,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, | |||
535 | lh_insert(mh,(char *)mp); | 560 | lh_insert(mh,(char *)mp); |
536 | } | 561 | } |
537 | 562 | ||
538 | MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ | 563 | MemCheck_on(); /* release MALLOC2 lock |
564 | * if num_disabled drops to 0 */ | ||
539 | } | 565 | } |
540 | break; | 566 | break; |
541 | } | 567 | } |
@@ -550,7 +576,7 @@ typedef struct mem_leak_st | |||
550 | long bytes; | 576 | long bytes; |
551 | } MEM_LEAK; | 577 | } MEM_LEAK; |
552 | 578 | ||
553 | static void print_leak(MEM *m, MEM_LEAK *l) | 579 | static void print_leak(const MEM *m, MEM_LEAK *l) |
554 | { | 580 | { |
555 | char buf[1024]; | 581 | char buf[1024]; |
556 | char *bufp = buf; | 582 | char *bufp = buf; |
@@ -626,7 +652,7 @@ static void print_leak(MEM *m, MEM_LEAK *l) | |||
626 | } | 652 | } |
627 | while(amip && amip->thread == ti); | 653 | while(amip && amip->thread == ti); |
628 | 654 | ||
629 | #ifdef LEVITTE_DEBUG | 655 | #ifdef LEVITTE_DEBUG_MEM |
630 | if (amip) | 656 | if (amip) |
631 | { | 657 | { |
632 | fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); | 658 | fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); |
@@ -635,69 +661,114 @@ static void print_leak(MEM *m, MEM_LEAK *l) | |||
635 | #endif | 661 | #endif |
636 | } | 662 | } |
637 | 663 | ||
664 | static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *) | ||
665 | |||
638 | void CRYPTO_mem_leaks(BIO *b) | 666 | void CRYPTO_mem_leaks(BIO *b) |
639 | { | 667 | { |
640 | MEM_LEAK ml; | 668 | MEM_LEAK ml; |
641 | char buf[80]; | 669 | char buf[80]; |
642 | 670 | ||
643 | if (mh == NULL) return; | 671 | if (mh == NULL && amih == NULL) |
672 | return; | ||
673 | |||
674 | MemCheck_off(); /* obtain MALLOC2 lock */ | ||
675 | |||
644 | ml.bio=b; | 676 | ml.bio=b; |
645 | ml.bytes=0; | 677 | ml.bytes=0; |
646 | ml.chunks=0; | 678 | ml.chunks=0; |
647 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | 679 | if (mh != NULL) |
648 | lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml); | 680 | lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), |
649 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | 681 | (char *)&ml); |
650 | if (ml.chunks != 0) | 682 | if (ml.chunks != 0) |
651 | { | 683 | { |
652 | sprintf(buf,"%ld bytes leaked in %d chunks\n", | 684 | sprintf(buf,"%ld bytes leaked in %d chunks\n", |
653 | ml.bytes,ml.chunks); | 685 | ml.bytes,ml.chunks); |
654 | BIO_puts(b,buf); | 686 | BIO_puts(b,buf); |
655 | } | 687 | } |
688 | else | ||
689 | { | ||
690 | /* Make sure that, if we found no leaks, memory-leak debugging itself | ||
691 | * does not introduce memory leaks (which might irritate | ||
692 | * external debugging tools). | ||
693 | * (When someone enables leak checking, but does not call | ||
694 | * this function, we declare it to be their fault.) | ||
695 | * | ||
696 | * XXX This should be in CRYPTO_mem_leaks_cb, | ||
697 | * and CRYPTO_mem_leaks should be implemented by | ||
698 | * using CRYPTO_mem_leaks_cb. | ||
699 | * (Also their should be a variant of lh_doall_arg | ||
700 | * that takes a function pointer instead of a void *; | ||
701 | * this would obviate the ugly and illegal | ||
702 | * void_fn_to_char kludge in CRYPTO_mem_leaks_cb. | ||
703 | * Otherwise the code police will come and get us.) | ||
704 | */ | ||
705 | int old_mh_mode; | ||
656 | 706 | ||
657 | #if 0 | 707 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
658 | lh_stats_bio(mh,b); | ||
659 | lh_node_stats_bio(mh,b); | ||
660 | lh_node_usage_stats_bio(mh,b); | ||
661 | #endif | ||
662 | } | ||
663 | |||
664 | union void_fn_to_char_u | ||
665 | { | ||
666 | char *char_p; | ||
667 | void (*fn_p)(); | ||
668 | }; | ||
669 | |||
670 | static void cb_leak(MEM *m, char *cb) | ||
671 | { | ||
672 | union void_fn_to_char_u mem_callback; | ||
673 | 708 | ||
674 | mem_callback.char_p=cb; | 709 | /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(), |
675 | mem_callback.fn_p(m->order,m->file,m->line,m->num,m->addr); | 710 | * which uses CRYPTO_is_mem_check_on */ |
676 | } | 711 | old_mh_mode = mh_mode; |
712 | mh_mode = CRYPTO_MEM_CHECK_OFF; | ||
677 | 713 | ||
678 | void CRYPTO_mem_leaks_cb(void (*cb)()) | 714 | if (mh != NULL) |
679 | { | 715 | { |
680 | union void_fn_to_char_u mem_cb; | 716 | lh_free(mh); |
717 | mh = NULL; | ||
718 | } | ||
719 | if (amih != NULL) | ||
720 | { | ||
721 | if (lh_num_items(amih) == 0) | ||
722 | { | ||
723 | lh_free(amih); | ||
724 | amih = NULL; | ||
725 | } | ||
726 | } | ||
681 | 727 | ||
682 | if (mh == NULL) return; | 728 | mh_mode = old_mh_mode; |
683 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | 729 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); |
684 | mem_cb.fn_p=cb; | 730 | } |
685 | lh_doall_arg(mh,(void (*)())cb_leak,mem_cb.char_p); | 731 | MemCheck_on(); /* release MALLOC2 lock */ |
686 | mem_cb.char_p=NULL; | ||
687 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | ||
688 | } | 732 | } |
689 | 733 | ||
690 | #ifndef NO_FP_API | 734 | #ifndef OPENSSL_NO_FP_API |
691 | void CRYPTO_mem_leaks_fp(FILE *fp) | 735 | void CRYPTO_mem_leaks_fp(FILE *fp) |
692 | { | 736 | { |
693 | BIO *b; | 737 | BIO *b; |
694 | 738 | ||
695 | if (mh == NULL) return; | 739 | if (mh == NULL) return; |
696 | if ((b=BIO_new(BIO_s_file())) == NULL) | 740 | /* Need to turn off memory checking when allocated BIOs ... especially |
697 | return; | 741 | * as we're creating them at a time when we're trying to check we've not |
742 | * left anything un-free()'d!! */ | ||
743 | MemCheck_off(); | ||
744 | b = BIO_new(BIO_s_file()); | ||
745 | MemCheck_on(); | ||
746 | if(!b) return; | ||
698 | BIO_set_fp(b,fp,BIO_NOCLOSE); | 747 | BIO_set_fp(b,fp,BIO_NOCLOSE); |
699 | CRYPTO_mem_leaks(b); | 748 | CRYPTO_mem_leaks(b); |
700 | BIO_free(b); | 749 | BIO_free(b); |
701 | } | 750 | } |
702 | #endif | 751 | #endif |
703 | 752 | ||
753 | |||
754 | |||
755 | /* FIXME: We really don't allow much to the callback. For example, it has | ||
756 | no chance of reaching the info stack for the item it processes. Should | ||
757 | it really be this way? -- Richard Levitte */ | ||
758 | /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h | ||
759 | * If this code is restructured, remove the callback type if it is no longer | ||
760 | * needed. -- Geoff Thorpe */ | ||
761 | static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb) | ||
762 | { | ||
763 | (**cb)(m->order,m->file,m->line,m->num,m->addr); | ||
764 | } | ||
765 | |||
766 | static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **) | ||
767 | |||
768 | void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) | ||
769 | { | ||
770 | if (mh == NULL) return; | ||
771 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | ||
772 | lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb); | ||
773 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | ||
774 | } | ||