/src/openssl/crypto/mem_dbg.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* crypto/mem_dbg.c */ |
2 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | | * All rights reserved. |
4 | | * |
5 | | * This package is an SSL implementation written |
6 | | * by Eric Young (eay@cryptsoft.com). |
7 | | * The implementation was written so as to conform with Netscapes SSL. |
8 | | * |
9 | | * This library is free for commercial and non-commercial use as long as |
10 | | * the following conditions are aheared to. The following conditions |
11 | | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | | * included with this distribution is covered by the same copyright terms |
14 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | | * |
16 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | | * the code are not to be removed. |
18 | | * If this package is used in a product, Eric Young should be given attribution |
19 | | * as the author of the parts of the library used. |
20 | | * This can be in the form of a textual message at program startup or |
21 | | * in documentation (online or textual) provided with the package. |
22 | | * |
23 | | * Redistribution and use in source and binary forms, with or without |
24 | | * modification, are permitted provided that the following conditions |
25 | | * are met: |
26 | | * 1. Redistributions of source code must retain the copyright |
27 | | * notice, this list of conditions and the following disclaimer. |
28 | | * 2. Redistributions in binary form must reproduce the above copyright |
29 | | * notice, this list of conditions and the following disclaimer in the |
30 | | * documentation and/or other materials provided with the distribution. |
31 | | * 3. All advertising materials mentioning features or use of this software |
32 | | * must display the following acknowledgement: |
33 | | * "This product includes cryptographic software written by |
34 | | * Eric Young (eay@cryptsoft.com)" |
35 | | * The word 'cryptographic' can be left out if the rouines from the library |
36 | | * being used are not cryptographic related :-). |
37 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | | * the apps directory (application code) you must include an acknowledgement: |
39 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | | * |
41 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | | * SUCH DAMAGE. |
52 | | * |
53 | | * The licence and distribution terms for any publically available version or |
54 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | | * copied and put under another distribution licence |
56 | | * [including the GNU Public Licence.] |
57 | | */ |
58 | | /* ==================================================================== |
59 | | * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. |
60 | | * |
61 | | * Redistribution and use in source and binary forms, with or without |
62 | | * modification, are permitted provided that the following conditions |
63 | | * are met: |
64 | | * |
65 | | * 1. Redistributions of source code must retain the above copyright |
66 | | * notice, this list of conditions and the following disclaimer. |
67 | | * |
68 | | * 2. Redistributions in binary form must reproduce the above copyright |
69 | | * notice, this list of conditions and the following disclaimer in |
70 | | * the documentation and/or other materials provided with the |
71 | | * distribution. |
72 | | * |
73 | | * 3. All advertising materials mentioning features or use of this |
74 | | * software must display the following acknowledgment: |
75 | | * "This product includes software developed by the OpenSSL Project |
76 | | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
77 | | * |
78 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
79 | | * endorse or promote products derived from this software without |
80 | | * prior written permission. For written permission, please contact |
81 | | * openssl-core@openssl.org. |
82 | | * |
83 | | * 5. Products derived from this software may not be called "OpenSSL" |
84 | | * nor may "OpenSSL" appear in their names without prior written |
85 | | * permission of the OpenSSL Project. |
86 | | * |
87 | | * 6. Redistributions of any form whatsoever must retain the following |
88 | | * acknowledgment: |
89 | | * "This product includes software developed by the OpenSSL Project |
90 | | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
91 | | * |
92 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
93 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
94 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
95 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
96 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
97 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
98 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
99 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
100 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
101 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
102 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
103 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
104 | | * ==================================================================== |
105 | | * |
106 | | * This product includes cryptographic software written by Eric Young |
107 | | * (eay@cryptsoft.com). This product includes software written by Tim |
108 | | * Hudson (tjh@cryptsoft.com). |
109 | | * |
110 | | */ |
111 | | |
112 | | #include <stdio.h> |
113 | | #include <stdlib.h> |
114 | | #include <time.h> |
115 | | #include "cryptlib.h" |
116 | | #include <openssl/crypto.h> |
117 | | #include <openssl/buffer.h> |
118 | | #include <openssl/bio.h> |
119 | | #include <openssl/lhash.h> |
120 | | |
121 | | static int mh_mode = CRYPTO_MEM_CHECK_OFF; |
122 | | /* |
123 | | * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when |
124 | | * the application asks for it (usually after library initialisation for |
125 | | * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only |
126 | | * temporarily when the library thinks that certain allocations should not be |
127 | | * checked (e.g. the data structures used for memory checking). It is not |
128 | | * suitable as an initial state: the library will unexpectedly enable memory |
129 | | * checking when it executes one of those sections that want to disable |
130 | | * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes |
131 | | * no sense whatsoever. |
132 | | */ |
133 | | |
134 | | static unsigned long order = 0; /* number of memory requests */ |
135 | | |
136 | | DECLARE_LHASH_OF(MEM); |
137 | | static LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as |
138 | | * key); access requires MALLOC2 lock */ |
139 | | |
140 | | typedef struct app_mem_info_st |
141 | | /*- |
142 | | * For application-defined information (static C-string `info') |
143 | | * to be displayed in memory leak list. |
144 | | * Each thread has its own stack. For applications, there is |
145 | | * CRYPTO_push_info("...") to push an entry, |
146 | | * CRYPTO_pop_info() to pop an entry, |
147 | | * CRYPTO_remove_all_info() to pop all entries. |
148 | | */ |
149 | | { |
150 | | CRYPTO_THREADID threadid; |
151 | | const char *file; |
152 | | int line; |
153 | | const char *info; |
154 | | struct app_mem_info_st *next; /* tail of thread's stack */ |
155 | | int references; |
156 | | } APP_INFO; |
157 | | |
158 | | static void app_info_free(APP_INFO *); |
159 | | |
160 | | DECLARE_LHASH_OF(APP_INFO); |
161 | | static LHASH_OF(APP_INFO) *amih = NULL; /* hash-table with those |
162 | | * app_mem_info_st's that are at the |
163 | | * top of their thread's stack (with |
164 | | * `thread' as key); access requires |
165 | | * MALLOC2 lock */ |
166 | | |
167 | | typedef struct mem_st |
168 | | /* memory-block description */ |
169 | | { |
170 | | void *addr; |
171 | | int num; |
172 | | const char *file; |
173 | | int line; |
174 | | CRYPTO_THREADID threadid; |
175 | | unsigned long order; |
176 | | time_t time; |
177 | | APP_INFO *app_info; |
178 | | } MEM; |
179 | | |
180 | | static long options = /* extra information to be recorded */ |
181 | | #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) |
182 | | V_CRYPTO_MDEBUG_TIME | |
183 | | #endif |
184 | | #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) |
185 | | V_CRYPTO_MDEBUG_THREAD | |
186 | | #endif |
187 | | 0; |
188 | | |
189 | | static unsigned int num_disable = 0; /* num_disable > 0 iff mh_mode == |
190 | | * CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */ |
191 | | |
192 | | /* |
193 | | * Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this |
194 | | * case (by the thread named in disabling_thread). |
195 | | */ |
196 | | static CRYPTO_THREADID disabling_threadid; |
197 | | |
198 | | static void app_info_free(APP_INFO *inf) |
199 | 0 | { |
200 | 0 | if (--(inf->references) <= 0) { |
201 | 0 | if (inf->next != NULL) { |
202 | 0 | app_info_free(inf->next); |
203 | 0 | } |
204 | 0 | OPENSSL_free(inf); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | | int CRYPTO_mem_ctrl(int mode) |
209 | 76 | { |
210 | 76 | int ret = mh_mode; |
211 | | |
212 | 76 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
213 | 76 | switch (mode) { |
214 | | /* |
215 | | * for applications (not to be called while multiple threads use the |
216 | | * library): |
217 | | */ |
218 | 0 | case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ |
219 | 0 | mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE; |
220 | 0 | num_disable = 0; |
221 | 0 | break; |
222 | 0 | case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ |
223 | 0 | mh_mode = 0; |
224 | 0 | num_disable = 0; /* should be true *before* MemCheck_stop is |
225 | | * used, or there'll be a lot of confusion */ |
226 | 0 | break; |
227 | | |
228 | | /* switch off temporarily (for library-internal use): */ |
229 | 38 | case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ |
230 | 38 | if (mh_mode & CRYPTO_MEM_CHECK_ON) { |
231 | 0 | CRYPTO_THREADID cur; |
232 | 0 | CRYPTO_THREADID_current(&cur); |
233 | | /* see if we don't have the MALLOC2 lock already */ |
234 | 0 | if (!num_disable |
235 | 0 | || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) { |
236 | | /* |
237 | | * Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed |
238 | | * while we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock |
239 | | * if somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot |
240 | | * release it because we block entry to this function). Give |
241 | | * them a chance, first, and then claim the locks in |
242 | | * appropriate order (long-time lock first). |
243 | | */ |
244 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); |
245 | | /* |
246 | | * Note that after we have waited for CRYPTO_LOCK_MALLOC2 and |
247 | | * CRYPTO_LOCK_MALLOC, we'll still be in the right "case" and |
248 | | * "if" branch because MemCheck_start and MemCheck_stop may |
249 | | * never be used while there are multiple OpenSSL threads. |
250 | | */ |
251 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); |
252 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
253 | 0 | mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; |
254 | 0 | CRYPTO_THREADID_cpy(&disabling_threadid, &cur); |
255 | 0 | } |
256 | 0 | num_disable++; |
257 | 0 | } |
258 | 38 | break; |
259 | 38 | case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ |
260 | 38 | if (mh_mode & CRYPTO_MEM_CHECK_ON) { |
261 | 0 | if (num_disable) { /* always true, or something is going wrong */ |
262 | 0 | num_disable--; |
263 | 0 | if (num_disable == 0) { |
264 | 0 | mh_mode |= CRYPTO_MEM_CHECK_ENABLE; |
265 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); |
266 | 0 | } |
267 | 0 | } |
268 | 0 | } |
269 | 38 | break; |
270 | | |
271 | 0 | default: |
272 | 0 | break; |
273 | 76 | } |
274 | 76 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); |
275 | 76 | return (ret); |
276 | 76 | } |
277 | | |
278 | | int CRYPTO_is_mem_check_on(void) |
279 | 25.4k | { |
280 | 25.4k | int ret = 0; |
281 | | |
282 | 25.4k | if (mh_mode & CRYPTO_MEM_CHECK_ON) { |
283 | 0 | CRYPTO_THREADID cur; |
284 | 0 | CRYPTO_THREADID_current(&cur); |
285 | 0 | CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); |
286 | |
|
287 | 0 | ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) |
288 | 0 | || CRYPTO_THREADID_cmp(&disabling_threadid, &cur); |
289 | |
|
290 | 0 | CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); |
291 | 0 | } |
292 | 25.4k | return (ret); |
293 | 25.4k | } |
294 | | |
295 | | void CRYPTO_dbg_set_options(long bits) |
296 | 0 | { |
297 | 0 | options = bits; |
298 | 0 | } |
299 | | |
300 | | long CRYPTO_dbg_get_options(void) |
301 | 0 | { |
302 | 0 | return options; |
303 | 0 | } |
304 | | |
305 | | static int mem_cmp(const MEM *a, const MEM *b) |
306 | 0 | { |
307 | | #ifdef _WIN64 |
308 | | const char *ap = (const char *)a->addr, *bp = (const char *)b->addr; |
309 | | if (ap == bp) |
310 | | return 0; |
311 | | else if (ap > bp) |
312 | | return 1; |
313 | | else |
314 | | return -1; |
315 | | #else |
316 | 0 | return (const char *)a->addr - (const char *)b->addr; |
317 | 0 | #endif |
318 | 0 | } |
319 | | |
320 | | static IMPLEMENT_LHASH_COMP_FN(mem, MEM) |
321 | | |
322 | | static unsigned long mem_hash(const MEM *a) |
323 | 0 | { |
324 | 0 | unsigned long ret; |
325 | |
|
326 | 0 | ret = (unsigned long)a->addr; |
327 | |
|
328 | 0 | ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251; |
329 | 0 | return (ret); |
330 | 0 | } |
331 | | |
332 | | static IMPLEMENT_LHASH_HASH_FN(mem, MEM) |
333 | | |
334 | | /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ |
335 | | static int app_info_cmp(const void *a_void, const void *b_void) |
336 | 0 | { |
337 | 0 | return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid, |
338 | 0 | &((const APP_INFO *)b_void)->threadid); |
339 | 0 | } |
340 | | |
341 | | static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO) |
342 | | |
343 | | static unsigned long app_info_hash(const APP_INFO *a) |
344 | 0 | { |
345 | 0 | unsigned long ret; |
346 | |
|
347 | 0 | ret = CRYPTO_THREADID_hash(&a->threadid); |
348 | | /* This is left in as a "who am I to question legacy?" measure */ |
349 | 0 | ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251; |
350 | 0 | return (ret); |
351 | 0 | } |
352 | | |
353 | | static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO) |
354 | | |
355 | | static APP_INFO *pop_info(void) |
356 | 0 | { |
357 | 0 | APP_INFO tmp; |
358 | 0 | APP_INFO *ret = NULL; |
359 | |
|
360 | 0 | if (amih != NULL) { |
361 | 0 | CRYPTO_THREADID_current(&tmp.threadid); |
362 | 0 | if ((ret = lh_APP_INFO_delete(amih, &tmp)) != NULL) { |
363 | 0 | APP_INFO *next = ret->next; |
364 | |
|
365 | 0 | if (next != NULL) { |
366 | 0 | next->references++; |
367 | 0 | (void)lh_APP_INFO_insert(amih, next); |
368 | 0 | } |
369 | | #ifdef LEVITTE_DEBUG_MEM |
370 | | if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid)) { |
371 | | fprintf(stderr, |
372 | | "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", |
373 | | CRYPTO_THREADID_hash(&ret->threadid), |
374 | | CRYPTO_THREADID_hash(&tmp.threadid)); |
375 | | abort(); |
376 | | } |
377 | | #endif |
378 | 0 | if (--(ret->references) <= 0) { |
379 | 0 | ret->next = NULL; |
380 | 0 | if (next != NULL) |
381 | 0 | next->references--; |
382 | 0 | OPENSSL_free(ret); |
383 | 0 | } |
384 | 0 | } |
385 | 0 | } |
386 | 0 | return (ret); |
387 | 0 | } |
388 | | |
389 | | int CRYPTO_push_info_(const char *info, const char *file, int line) |
390 | 12.7k | { |
391 | 12.7k | APP_INFO *ami, *amim; |
392 | 12.7k | int ret = 0; |
393 | | |
394 | 12.7k | if (is_MemCheck_on()) { |
395 | 0 | MemCheck_off(); /* obtain MALLOC2 lock */ |
396 | |
|
397 | 0 | if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) { |
398 | 0 | ret = 0; |
399 | 0 | goto err; |
400 | 0 | } |
401 | 0 | if (amih == NULL) { |
402 | 0 | if ((amih = lh_APP_INFO_new()) == NULL) { |
403 | 0 | OPENSSL_free(ami); |
404 | 0 | ret = 0; |
405 | 0 | goto err; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | 0 | CRYPTO_THREADID_current(&ami->threadid); |
410 | 0 | ami->file = file; |
411 | 0 | ami->line = line; |
412 | 0 | ami->info = info; |
413 | 0 | ami->references = 1; |
414 | 0 | ami->next = NULL; |
415 | |
|
416 | 0 | if ((amim = lh_APP_INFO_insert(amih, ami)) != NULL) { |
417 | | #ifdef LEVITTE_DEBUG_MEM |
418 | | if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid)) { |
419 | | fprintf(stderr, |
420 | | "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", |
421 | | CRYPTO_THREADID_hash(&amim->threadid), |
422 | | CRYPTO_THREADID_hash(&ami->threadid)); |
423 | | abort(); |
424 | | } |
425 | | #endif |
426 | 0 | ami->next = amim; |
427 | 0 | } |
428 | 0 | err: |
429 | 0 | MemCheck_on(); /* release MALLOC2 lock */ |
430 | 0 | } |
431 | | |
432 | 12.7k | return (ret); |
433 | 12.7k | } |
434 | | |
435 | | int CRYPTO_pop_info(void) |
436 | 12.7k | { |
437 | 12.7k | int ret = 0; |
438 | | |
439 | 12.7k | if (is_MemCheck_on()) { /* _must_ be true, or something went severely |
440 | | * wrong */ |
441 | 0 | MemCheck_off(); /* obtain MALLOC2 lock */ |
442 | |
|
443 | 0 | ret = (pop_info() != NULL); |
444 | |
|
445 | 0 | MemCheck_on(); /* release MALLOC2 lock */ |
446 | 0 | } |
447 | 12.7k | return (ret); |
448 | 12.7k | } |
449 | | |
450 | | int CRYPTO_remove_all_info(void) |
451 | 0 | { |
452 | 0 | int ret = 0; |
453 | |
|
454 | 0 | if (is_MemCheck_on()) { /* _must_ be true */ |
455 | 0 | MemCheck_off(); /* obtain MALLOC2 lock */ |
456 | |
|
457 | 0 | while (pop_info() != NULL) |
458 | 0 | ret++; |
459 | |
|
460 | 0 | MemCheck_on(); /* release MALLOC2 lock */ |
461 | 0 | } |
462 | 0 | return (ret); |
463 | 0 | } |
464 | | |
465 | | static unsigned long break_order_num = 0; |
466 | | void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, |
467 | | int before_p) |
468 | 0 | { |
469 | 0 | MEM *m, *mm; |
470 | 0 | APP_INFO tmp, *amim; |
471 | |
|
472 | 0 | switch (before_p & 127) { |
473 | 0 | case 0: |
474 | 0 | break; |
475 | 0 | case 1: |
476 | 0 | if (addr == NULL) |
477 | 0 | break; |
478 | | |
479 | 0 | if (is_MemCheck_on()) { |
480 | 0 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
481 | 0 | if ((m = (MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) { |
482 | 0 | OPENSSL_free(addr); |
483 | 0 | MemCheck_on(); /* release MALLOC2 lock if num_disabled drops |
484 | | * to 0 */ |
485 | 0 | return; |
486 | 0 | } |
487 | 0 | if (mh == NULL) { |
488 | 0 | if ((mh = lh_MEM_new()) == NULL) { |
489 | 0 | OPENSSL_free(addr); |
490 | 0 | OPENSSL_free(m); |
491 | 0 | addr = NULL; |
492 | 0 | goto err; |
493 | 0 | } |
494 | 0 | } |
495 | | |
496 | 0 | m->addr = addr; |
497 | 0 | m->file = file; |
498 | 0 | m->line = line; |
499 | 0 | m->num = num; |
500 | 0 | if (options & V_CRYPTO_MDEBUG_THREAD) |
501 | 0 | CRYPTO_THREADID_current(&m->threadid); |
502 | 0 | else |
503 | 0 | memset(&m->threadid, 0, sizeof(m->threadid)); |
504 | |
|
505 | 0 | if (order == break_order_num) { |
506 | | /* BREAK HERE */ |
507 | 0 | m->order = order; |
508 | 0 | } |
509 | 0 | m->order = order++; |
510 | | #ifdef LEVITTE_DEBUG_MEM |
511 | | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n", |
512 | | m->order, (before_p & 128) ? '*' : '+', m->addr, m->num); |
513 | | #endif |
514 | 0 | if (options & V_CRYPTO_MDEBUG_TIME) |
515 | 0 | m->time = time(NULL); |
516 | 0 | else |
517 | 0 | m->time = 0; |
518 | |
|
519 | 0 | CRYPTO_THREADID_current(&tmp.threadid); |
520 | 0 | m->app_info = NULL; |
521 | 0 | if (amih != NULL |
522 | 0 | && (amim = lh_APP_INFO_retrieve(amih, &tmp)) != NULL) { |
523 | 0 | m->app_info = amim; |
524 | 0 | amim->references++; |
525 | 0 | } |
526 | |
|
527 | 0 | if ((mm = lh_MEM_insert(mh, m)) != NULL) { |
528 | | /* Not good, but don't sweat it */ |
529 | 0 | if (mm->app_info != NULL) { |
530 | 0 | mm->app_info->references--; |
531 | 0 | } |
532 | 0 | OPENSSL_free(mm); |
533 | 0 | } |
534 | 0 | err: |
535 | 0 | MemCheck_on(); /* release MALLOC2 lock if num_disabled drops |
536 | | * to 0 */ |
537 | 0 | } |
538 | 0 | break; |
539 | 0 | } |
540 | 0 | return; |
541 | 0 | } |
542 | | |
543 | | void CRYPTO_dbg_free(void *addr, int before_p) |
544 | 0 | { |
545 | 0 | MEM m, *mp; |
546 | |
|
547 | 0 | switch (before_p) { |
548 | 0 | case 0: |
549 | 0 | if (addr == NULL) |
550 | 0 | break; |
551 | | |
552 | 0 | if (is_MemCheck_on() && (mh != NULL)) { |
553 | 0 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
554 | |
|
555 | 0 | m.addr = addr; |
556 | 0 | mp = lh_MEM_delete(mh, &m); |
557 | 0 | if (mp != NULL) { |
558 | | #ifdef LEVITTE_DEBUG_MEM |
559 | | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n", |
560 | | mp->order, mp->addr, mp->num); |
561 | | #endif |
562 | 0 | if (mp->app_info != NULL) |
563 | 0 | app_info_free(mp->app_info); |
564 | 0 | OPENSSL_free(mp); |
565 | 0 | } |
566 | |
|
567 | 0 | MemCheck_on(); /* release MALLOC2 lock if num_disabled drops |
568 | | * to 0 */ |
569 | 0 | } |
570 | 0 | break; |
571 | 0 | case 1: |
572 | 0 | break; |
573 | 0 | } |
574 | 0 | } |
575 | | |
576 | | void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, |
577 | | const char *file, int line, int before_p) |
578 | 0 | { |
579 | 0 | MEM m, *mp; |
580 | |
|
581 | | #ifdef LEVITTE_DEBUG_MEM |
582 | | fprintf(stderr, |
583 | | "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", |
584 | | addr1, addr2, num, file, line, before_p); |
585 | | #endif |
586 | |
|
587 | 0 | switch (before_p) { |
588 | 0 | case 0: |
589 | 0 | break; |
590 | 0 | case 1: |
591 | 0 | if (addr2 == NULL) |
592 | 0 | break; |
593 | | |
594 | 0 | if (addr1 == NULL) { |
595 | 0 | CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); |
596 | 0 | break; |
597 | 0 | } |
598 | | |
599 | 0 | if (is_MemCheck_on()) { |
600 | 0 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
601 | |
|
602 | 0 | m.addr = addr1; |
603 | 0 | mp = lh_MEM_delete(mh, &m); |
604 | 0 | if (mp != NULL) { |
605 | | #ifdef LEVITTE_DEBUG_MEM |
606 | | fprintf(stderr, |
607 | | "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n", |
608 | | mp->order, mp->addr, mp->num, addr2, num); |
609 | | #endif |
610 | 0 | mp->addr = addr2; |
611 | 0 | mp->num = num; |
612 | 0 | (void)lh_MEM_insert(mh, mp); |
613 | 0 | } |
614 | |
|
615 | 0 | MemCheck_on(); /* release MALLOC2 lock if num_disabled drops |
616 | | * to 0 */ |
617 | 0 | } |
618 | 0 | break; |
619 | 0 | } |
620 | 0 | return; |
621 | 0 | } |
622 | | |
623 | | typedef struct mem_leak_st { |
624 | | BIO *bio; |
625 | | int chunks; |
626 | | long bytes; |
627 | | } MEM_LEAK; |
628 | | |
629 | | static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) |
630 | 0 | { |
631 | 0 | char buf[1024]; |
632 | 0 | char *bufp = buf; |
633 | 0 | APP_INFO *amip; |
634 | 0 | int ami_cnt; |
635 | 0 | struct tm *lcl = NULL; |
636 | 0 | CRYPTO_THREADID ti; |
637 | |
|
638 | 0 | #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) |
639 | |
|
640 | 0 | if (m->addr == (char *)l->bio) |
641 | 0 | return; |
642 | | |
643 | 0 | if (options & V_CRYPTO_MDEBUG_TIME) { |
644 | 0 | lcl = localtime(&m->time); |
645 | |
|
646 | 0 | BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ", |
647 | 0 | lcl->tm_hour, lcl->tm_min, lcl->tm_sec); |
648 | 0 | bufp += strlen(bufp); |
649 | 0 | } |
650 | |
|
651 | 0 | BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ", |
652 | 0 | m->order, m->file, m->line); |
653 | 0 | bufp += strlen(bufp); |
654 | |
|
655 | 0 | if (options & V_CRYPTO_MDEBUG_THREAD) { |
656 | 0 | BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", |
657 | 0 | CRYPTO_THREADID_hash(&m->threadid)); |
658 | 0 | bufp += strlen(bufp); |
659 | 0 | } |
660 | |
|
661 | 0 | BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n", |
662 | 0 | m->num, (unsigned long)m->addr); |
663 | 0 | bufp += strlen(bufp); |
664 | |
|
665 | 0 | BIO_puts(l->bio, buf); |
666 | |
|
667 | 0 | l->chunks++; |
668 | 0 | l->bytes += m->num; |
669 | |
|
670 | 0 | amip = m->app_info; |
671 | 0 | ami_cnt = 0; |
672 | 0 | if (!amip) |
673 | 0 | return; |
674 | 0 | CRYPTO_THREADID_cpy(&ti, &amip->threadid); |
675 | |
|
676 | 0 | do { |
677 | 0 | int buf_len; |
678 | 0 | int info_len; |
679 | |
|
680 | 0 | ami_cnt++; |
681 | 0 | memset(buf, '>', ami_cnt); |
682 | 0 | BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, |
683 | 0 | " thread=%lu, file=%s, line=%d, info=\"", |
684 | 0 | CRYPTO_THREADID_hash(&amip->threadid), amip->file, |
685 | 0 | amip->line); |
686 | 0 | buf_len = strlen(buf); |
687 | 0 | info_len = strlen(amip->info); |
688 | 0 | if (128 - buf_len - 3 < info_len) { |
689 | 0 | memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); |
690 | 0 | buf_len = 128 - 3; |
691 | 0 | } else { |
692 | 0 | BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len); |
693 | 0 | buf_len = strlen(buf); |
694 | 0 | } |
695 | 0 | BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n"); |
696 | |
|
697 | 0 | BIO_puts(l->bio, buf); |
698 | |
|
699 | 0 | amip = amip->next; |
700 | 0 | } |
701 | 0 | while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti)); |
702 | |
|
703 | | #ifdef LEVITTE_DEBUG_MEM |
704 | | if (amip) { |
705 | | fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); |
706 | | abort(); |
707 | | } |
708 | | #endif |
709 | 0 | } |
710 | | |
711 | | static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK) |
712 | | |
713 | | void CRYPTO_mem_leaks(BIO *b) |
714 | 0 | { |
715 | 0 | MEM_LEAK ml; |
716 | |
|
717 | 0 | if (mh == NULL && amih == NULL) |
718 | 0 | return; |
719 | | |
720 | 0 | MemCheck_off(); /* obtain MALLOC2 lock */ |
721 | |
|
722 | 0 | ml.bio = b; |
723 | 0 | ml.bytes = 0; |
724 | 0 | ml.chunks = 0; |
725 | 0 | if (mh != NULL) |
726 | 0 | lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK, &ml); |
727 | 0 | if (ml.chunks != 0) { |
728 | 0 | BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks); |
729 | | #ifdef CRYPTO_MDEBUG_ABORT |
730 | | abort(); |
731 | | #endif |
732 | 0 | } else { |
733 | | /* |
734 | | * Make sure that, if we found no leaks, memory-leak debugging itself |
735 | | * does not introduce memory leaks (which might irritate external |
736 | | * debugging tools). (When someone enables leak checking, but does not |
737 | | * call this function, we declare it to be their fault.) XXX This |
738 | | * should be in CRYPTO_mem_leaks_cb, and CRYPTO_mem_leaks should be |
739 | | * implemented by using CRYPTO_mem_leaks_cb. (Also there should be a |
740 | | * variant of lh_doall_arg that takes a function pointer instead of a |
741 | | * void *; this would obviate the ugly and illegal void_fn_to_char |
742 | | * kludge in CRYPTO_mem_leaks_cb. Otherwise the code police will come |
743 | | * and get us.) |
744 | | */ |
745 | 0 | int old_mh_mode; |
746 | |
|
747 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
748 | | |
749 | | /* |
750 | | * avoid deadlock when lh_free() uses CRYPTO_dbg_free(), which uses |
751 | | * CRYPTO_is_mem_check_on |
752 | | */ |
753 | 0 | old_mh_mode = mh_mode; |
754 | 0 | mh_mode = CRYPTO_MEM_CHECK_OFF; |
755 | |
|
756 | 0 | if (mh != NULL) { |
757 | 0 | lh_MEM_free(mh); |
758 | 0 | mh = NULL; |
759 | 0 | } |
760 | 0 | if (amih != NULL) { |
761 | 0 | if (lh_APP_INFO_num_items(amih) == 0) { |
762 | 0 | lh_APP_INFO_free(amih); |
763 | 0 | amih = NULL; |
764 | 0 | } |
765 | 0 | } |
766 | |
|
767 | 0 | mh_mode = old_mh_mode; |
768 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); |
769 | 0 | } |
770 | 0 | MemCheck_on(); /* release MALLOC2 lock */ |
771 | 0 | } |
772 | | |
773 | | #ifndef OPENSSL_NO_FP_API |
774 | | void CRYPTO_mem_leaks_fp(FILE *fp) |
775 | 0 | { |
776 | 0 | BIO *b; |
777 | |
|
778 | 0 | if (mh == NULL) |
779 | 0 | return; |
780 | | /* |
781 | | * Need to turn off memory checking when allocated BIOs ... especially as |
782 | | * we're creating them at a time when we're trying to check we've not |
783 | | * left anything un-free()'d!! |
784 | | */ |
785 | 0 | MemCheck_off(); |
786 | 0 | b = BIO_new(BIO_s_file()); |
787 | 0 | MemCheck_on(); |
788 | 0 | if (!b) |
789 | 0 | return; |
790 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
791 | 0 | CRYPTO_mem_leaks(b); |
792 | 0 | BIO_free(b); |
793 | 0 | } |
794 | | #endif |
795 | | |
796 | | /* |
797 | | * FIXME: We really don't allow much to the callback. For example, it has no |
798 | | * chance of reaching the info stack for the item it processes. Should it |
799 | | * really be this way? -- Richard Levitte |
800 | | */ |
801 | | /* |
802 | | * NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside |
803 | | * crypto.h If this code is restructured, remove the callback type if it is |
804 | | * no longer needed. -- Geoff Thorpe |
805 | | */ |
806 | | |
807 | | /* |
808 | | * Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it is a |
809 | | * function pointer and conversion to void * is prohibited. Instead pass its |
810 | | * address |
811 | | */ |
812 | | |
813 | | typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB; |
814 | | |
815 | | static void cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb) |
816 | 0 | { |
817 | 0 | (*cb) (m->order, m->file, m->line, m->num, m->addr); |
818 | 0 | } |
819 | | |
820 | | static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB) |
821 | | |
822 | | void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) |
823 | 0 | { |
824 | 0 | if (mh == NULL) |
825 | 0 | return; |
826 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); |
827 | 0 | lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB, |
828 | 0 | &cb); |
829 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); |
830 | 0 | } |