diff options
Diffstat (limited to '')
| -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 | } | ||
