diff options
author | beck <> | 2000-03-19 11:13:58 +0000 |
---|---|---|
committer | beck <> | 2000-03-19 11:13:58 +0000 |
commit | 796d609550df3a33fc11468741c5d2f6d3df4c11 (patch) | |
tree | 6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/mem.c | |
parent | 5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff) | |
download | openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2 openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip |
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2
if you are using the ssl26 packages for ssh and other things to work you will
need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/mem.c')
-rw-r--r-- | src/lib/libcrypto/mem.c | 432 |
1 files changed, 132 insertions, 300 deletions
diff --git a/src/lib/libcrypto/mem.c b/src/lib/libcrypto/mem.c index 61fc1e184e..5a661e5f45 100644 --- a/src/lib/libcrypto/mem.c +++ b/src/lib/libcrypto/mem.c | |||
@@ -59,371 +59,203 @@ | |||
59 | #include <stdio.h> | 59 | #include <stdio.h> |
60 | #include <stdlib.h> | 60 | #include <stdlib.h> |
61 | #include <openssl/crypto.h> | 61 | #include <openssl/crypto.h> |
62 | #ifdef CRYPTO_MDEBUG_TIME | ||
63 | # include <time.h> | ||
64 | #endif | ||
65 | #include <openssl/buffer.h> | ||
66 | #include <openssl/bio.h> | ||
67 | #include <openssl/lhash.h> | ||
68 | #include "cryptlib.h" | 62 | #include "cryptlib.h" |
69 | 63 | ||
70 | /* #ifdef CRYPTO_MDEBUG */ | ||
71 | /* static int mh_mode=CRYPTO_MEM_CHECK_ON; */ | ||
72 | /* #else */ | ||
73 | static int mh_mode=CRYPTO_MEM_CHECK_OFF; | ||
74 | /* #endif */ | ||
75 | /* State CRYPTO_MEM_CHECK_ON exists only temporarily when the library | ||
76 | * thinks that certain allocations should not be checked (e.g. the data | ||
77 | * structures used for memory checking). It is not suitable as an initial | ||
78 | * state: the library will unexpectedly enable memory checking when it | ||
79 | * executes one of those sections that want to disable checking | ||
80 | * temporarily. | ||
81 | * | ||
82 | * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever. | ||
83 | */ | ||
84 | |||
85 | static unsigned long order=0; | ||
86 | |||
87 | static LHASH *mh=NULL; | ||
88 | 64 | ||
89 | typedef struct mem_st | 65 | static int allow_customize = 1; /* we provide flexible functions for */ |
90 | { | 66 | static int allow_customize_debug = 1;/* exchanging memory-related functions at |
91 | char *addr; | 67 | * run-time, but this must be done |
92 | int num; | 68 | * before any blocks are actually |
93 | const char *file; | 69 | * allocated; or we'll run into huge |
94 | int line; | 70 | * problems when malloc/free pairs |
95 | #ifdef CRYPTO_MDEBUG_THREAD | 71 | * don't match etc. */ |
96 | unsigned long thread; | 72 | |
73 | /* may be changed as long as `allow_customize' is set */ | ||
74 | static void *(*malloc_locked_func)(size_t) = malloc; | ||
75 | static void (*free_locked_func)(void *) = free; | ||
76 | static void *(*malloc_func)(size_t) = malloc; | ||
77 | static void *(*realloc_func)(void *, size_t)= realloc; | ||
78 | static void (*free_func)(void *) = free; | ||
79 | |||
80 | /* may be changed as long as `allow_customize_debug' is set */ | ||
81 | /* XXX use correct function pointer types */ | ||
82 | #ifdef CRYPTO_MDEBUG | ||
83 | /* use default functions from mem_dbg.c */ | ||
84 | static void (*malloc_debug_func)()= (void (*)())CRYPTO_dbg_malloc; | ||
85 | static void (*realloc_debug_func)()= (void (*)())CRYPTO_dbg_realloc; | ||
86 | static void (*free_debug_func)()= (void (*)())CRYPTO_dbg_free; | ||
87 | static void (*set_debug_options_func)()= (void (*)())CRYPTO_dbg_set_options; | ||
88 | static long (*get_debug_options_func)()= (long (*)())CRYPTO_dbg_get_options; | ||
89 | #else | ||
90 | /* applications can use CRYPTO_malloc_debug_init() to select above case | ||
91 | * at run-time */ | ||
92 | static void (*malloc_debug_func)()= NULL; | ||
93 | static void (*realloc_debug_func)()= NULL; | ||
94 | static void (*free_debug_func)()= NULL; | ||
95 | static void (*set_debug_options_func)()= NULL; | ||
96 | static long (*get_debug_options_func)()= NULL; | ||
97 | #endif | 97 | #endif |
98 | unsigned long order; | ||
99 | #ifdef CRYPTO_MDEBUG_TIME | ||
100 | time_t time; | ||
101 | #endif | ||
102 | } MEM; | ||
103 | |||
104 | int CRYPTO_mem_ctrl(int mode) | ||
105 | { | ||
106 | int ret=mh_mode; | ||
107 | |||
108 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | ||
109 | switch (mode) | ||
110 | { | ||
111 | /* for applications: */ | ||
112 | case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ | ||
113 | mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; | ||
114 | break; | ||
115 | case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ | ||
116 | mh_mode = 0; | ||
117 | break; | ||
118 | 98 | ||
119 | /* switch off temporarily (for library-internal use): */ | ||
120 | case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ | ||
121 | mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE; | ||
122 | break; | ||
123 | case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ | ||
124 | if (mh_mode&CRYPTO_MEM_CHECK_ON) | ||
125 | mh_mode|=CRYPTO_MEM_CHECK_ENABLE; | ||
126 | break; | ||
127 | 99 | ||
128 | default: | 100 | int CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t), |
129 | break; | 101 | void (*f)(void *)) |
130 | } | ||
131 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
132 | return(ret); | ||
133 | } | ||
134 | |||
135 | static int mem_cmp(MEM *a, MEM *b) | ||
136 | { | ||
137 | return(a->addr - b->addr); | ||
138 | } | ||
139 | |||
140 | static unsigned long mem_hash(MEM *a) | ||
141 | { | 102 | { |
142 | unsigned long ret; | 103 | if (!allow_customize) |
143 | 104 | return 0; | |
144 | ret=(unsigned long)a->addr; | 105 | if ((m == NULL) || (r == NULL) || (f == NULL)) |
145 | 106 | return 0; | |
146 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; | ||
147 | return(ret); | ||
148 | } | ||
149 | |||
150 | static char *(*malloc_locked_func)()=(char *(*)())malloc; | ||
151 | static void (*free_locked_func)()=(void (*)())free; | ||
152 | static char *(*malloc_func)()= (char *(*)())malloc; | ||
153 | static char *(*realloc_func)()= (char *(*)())realloc; | ||
154 | static void (*free_func)()= (void (*)())free; | ||
155 | |||
156 | void CRYPTO_set_mem_functions(char *(*m)(), char *(*r)(), void (*f)()) | ||
157 | { | ||
158 | if ((m == NULL) || (r == NULL) || (f == NULL)) return; | ||
159 | malloc_func=m; | 107 | malloc_func=m; |
160 | realloc_func=r; | 108 | realloc_func=r; |
161 | free_func=f; | 109 | free_func=f; |
162 | malloc_locked_func=m; | 110 | malloc_locked_func=m; |
163 | free_locked_func=f; | 111 | free_locked_func=f; |
112 | return 1; | ||
164 | } | 113 | } |
165 | 114 | ||
166 | void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*f)()) | 115 | int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*f)(void *)) |
167 | { | 116 | { |
168 | if ((m == NULL) || (f == NULL)) return; | 117 | if (!allow_customize) |
118 | return 0; | ||
119 | if ((m == NULL) || (f == NULL)) | ||
120 | return 0; | ||
169 | malloc_locked_func=m; | 121 | malloc_locked_func=m; |
170 | free_locked_func=f; | 122 | free_locked_func=f; |
123 | return 1; | ||
124 | } | ||
125 | |||
126 | int CRYPTO_set_mem_debug_functions(void (*m)(), void (*r)(), void (*f)(),void (*so)(),long (*go)()) | ||
127 | { | ||
128 | if (!allow_customize_debug) | ||
129 | return 0; | ||
130 | malloc_debug_func=m; | ||
131 | realloc_debug_func=r; | ||
132 | free_debug_func=f; | ||
133 | set_debug_options_func=so; | ||
134 | get_debug_options_func=go; | ||
135 | return 1; | ||
171 | } | 136 | } |
172 | 137 | ||
173 | void CRYPTO_get_mem_functions(char *(**m)(), char *(**r)(), void (**f)()) | 138 | void CRYPTO_get_mem_functions(void *(**m)(size_t), void *(**r)(void *, size_t), |
139 | void (**f)(void *)) | ||
174 | { | 140 | { |
175 | if (m != NULL) *m=malloc_func; | 141 | if (m != NULL) *m=malloc_func; |
176 | if (r != NULL) *r=realloc_func; | 142 | if (r != NULL) *r=realloc_func; |
177 | if (f != NULL) *f=free_func; | 143 | if (f != NULL) *f=free_func; |
178 | } | 144 | } |
179 | 145 | ||
180 | void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)()) | 146 | void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *)) |
181 | { | 147 | { |
182 | if (m != NULL) *m=malloc_locked_func; | 148 | if (m != NULL) *m=malloc_locked_func; |
183 | if (f != NULL) *f=free_locked_func; | 149 | if (f != NULL) *f=free_locked_func; |
184 | } | 150 | } |
185 | 151 | ||
186 | void *CRYPTO_malloc_locked(int num) | 152 | void CRYPTO_get_mem_debug_functions(void (**m)(), void (**r)(), void (**f)(),void (**so)(),long (**go)()) |
187 | { | 153 | { |
188 | return(malloc_locked_func(num)); | 154 | if (m != NULL) *m=malloc_debug_func; |
155 | if (r != NULL) *r=realloc_debug_func; | ||
156 | if (f != NULL) *f=free_debug_func; | ||
157 | if (so != NULL) *so=set_debug_options_func; | ||
158 | if (go != NULL) *go=get_debug_options_func; | ||
189 | } | 159 | } |
190 | 160 | ||
191 | void CRYPTO_free_locked(void *str) | ||
192 | { | ||
193 | free_locked_func(str); | ||
194 | } | ||
195 | 161 | ||
196 | void *CRYPTO_malloc(int num) | 162 | void *CRYPTO_malloc_locked(int num, const char *file, int line) |
197 | { | 163 | { |
198 | return(malloc_func(num)); | 164 | char *ret = NULL; |
199 | } | ||
200 | 165 | ||
201 | void *CRYPTO_realloc(void *str, int num) | 166 | allow_customize = 0; |
202 | { | 167 | if (malloc_debug_func != NULL) |
203 | return(realloc_func(str,num)); | ||
204 | } | ||
205 | |||
206 | void CRYPTO_free(void *str) | ||
207 | { | ||
208 | free_func(str); | ||
209 | } | ||
210 | |||
211 | static unsigned long break_order_num=0; | ||
212 | void *CRYPTO_dbg_malloc(int num, const char *file, int line) | ||
213 | { | ||
214 | char *ret; | ||
215 | MEM *m,*mm; | ||
216 | |||
217 | if ((ret=malloc_func(num)) == NULL) | ||
218 | return(NULL); | ||
219 | |||
220 | if (mh_mode & CRYPTO_MEM_CHECK_ENABLE) | ||
221 | { | 168 | { |
222 | MemCheck_off(); | 169 | allow_customize_debug = 0; |
223 | if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) | 170 | malloc_debug_func(NULL, num, file, line, 0); |
224 | { | ||
225 | Free(ret); | ||
226 | MemCheck_on(); | ||
227 | return(NULL); | ||
228 | } | ||
229 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | ||
230 | if (mh == NULL) | ||
231 | { | ||
232 | if ((mh=lh_new(mem_hash,mem_cmp)) == NULL) | ||
233 | { | ||
234 | Free(ret); | ||
235 | Free(m); | ||
236 | ret=NULL; | ||
237 | goto err; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | m->addr=ret; | ||
242 | m->file=file; | ||
243 | m->line=line; | ||
244 | m->num=num; | ||
245 | #ifdef CRYPTO_MDEBUG_THREAD | ||
246 | m->thread=CRYPTO_thread_id(); | ||
247 | #endif | ||
248 | if (order == break_order_num) | ||
249 | { | ||
250 | /* BREAK HERE */ | ||
251 | m->order=order; | ||
252 | } | ||
253 | m->order=order++; | ||
254 | #ifdef CRYPTO_MDEBUG_TIME | ||
255 | m->time=time(NULL); | ||
256 | #endif | ||
257 | if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL) | ||
258 | { | ||
259 | /* Not good, but don't sweat it */ | ||
260 | Free(mm); | ||
261 | } | ||
262 | err: | ||
263 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
264 | MemCheck_on(); | ||
265 | } | 171 | } |
266 | return(ret); | 172 | ret = malloc_locked_func(num); |
173 | #ifdef LEVITTE_DEBUG | ||
174 | fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num); | ||
175 | #endif | ||
176 | if (malloc_debug_func != NULL) | ||
177 | malloc_debug_func(ret, num, file, line, 1); | ||
178 | |||
179 | return ret; | ||
267 | } | 180 | } |
268 | 181 | ||
269 | void CRYPTO_dbg_free(void *addr) | 182 | void CRYPTO_free_locked(void *str) |
270 | { | 183 | { |
271 | MEM m,*mp; | 184 | if (free_debug_func != NULL) |
272 | 185 | free_debug_func(str, 0); | |
273 | if ((mh_mode & CRYPTO_MEM_CHECK_ENABLE) && (mh != NULL)) | 186 | #ifdef LEVITTE_DEBUG |
274 | { | 187 | fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str); |
275 | MemCheck_off(); | 188 | #endif |
276 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | 189 | free_locked_func(str); |
277 | m.addr=addr; | 190 | if (free_debug_func != NULL) |
278 | mp=(MEM *)lh_delete(mh,(char *)&m); | 191 | free_debug_func(NULL, 1); |
279 | if (mp != NULL) | ||
280 | Free(mp); | ||
281 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
282 | MemCheck_on(); | ||
283 | } | ||
284 | free_func(addr); | ||
285 | } | 192 | } |
286 | 193 | ||
287 | void *CRYPTO_dbg_realloc(void *addr, int num, const char *file, int line) | 194 | void *CRYPTO_malloc(int num, const char *file, int line) |
288 | { | 195 | { |
289 | char *ret; | 196 | char *ret = NULL; |
290 | MEM m,*mp; | ||
291 | |||
292 | ret=realloc_func(addr,num); | ||
293 | if (ret == addr) return(ret); | ||
294 | 197 | ||
295 | if (mh_mode & CRYPTO_MEM_CHECK_ENABLE) | 198 | allow_customize = 0; |
199 | if (malloc_debug_func != NULL) | ||
296 | { | 200 | { |
297 | MemCheck_off(); | 201 | allow_customize_debug = 0; |
298 | if (ret == NULL) return(NULL); | 202 | malloc_debug_func(NULL, num, file, line, 0); |
299 | m.addr=addr; | ||
300 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | ||
301 | mp=(MEM *)lh_delete(mh,(char *)&m); | ||
302 | if (mp != NULL) | ||
303 | { | ||
304 | mp->addr=ret; | ||
305 | lh_insert(mh,(char *)mp); | ||
306 | } | ||
307 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
308 | MemCheck_on(); | ||
309 | } | 203 | } |
310 | return(ret); | 204 | ret = malloc_func(num); |
311 | } | 205 | #ifdef LEVITTE_DEBUG |
312 | 206 | fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num); | |
313 | void *CRYPTO_remalloc(void *a, int n) | 207 | #endif |
314 | { | 208 | if (malloc_debug_func != NULL) |
315 | if (a != NULL) Free(a); | 209 | malloc_debug_func(ret, num, file, line, 1); |
316 | a=(char *)Malloc(n); | ||
317 | return(a); | ||
318 | } | ||
319 | 210 | ||
320 | void *CRYPTO_dbg_remalloc(void *a, int n, const char *file, int line) | 211 | return ret; |
321 | { | ||
322 | if (a != NULL) CRYPTO_dbg_free(a); | ||
323 | a=(char *)CRYPTO_dbg_malloc(n,file,line); | ||
324 | return(a); | ||
325 | } | 212 | } |
326 | 213 | ||
327 | 214 | void *CRYPTO_realloc(void *str, int num, const char *file, int line) | |
328 | typedef struct mem_leak_st | ||
329 | { | 215 | { |
330 | BIO *bio; | 216 | char *ret = NULL; |
331 | int chunks; | ||
332 | long bytes; | ||
333 | } MEM_LEAK; | ||
334 | 217 | ||
335 | static void print_leak(MEM *m, MEM_LEAK *l) | 218 | if (realloc_debug_func != NULL) |
336 | { | 219 | realloc_debug_func(str, NULL, num, file, line, 0); |
337 | char buf[128]; | 220 | ret = realloc_func(str,num); |
338 | #ifdef CRYPTO_MDEBUG_TIME | 221 | #ifdef LEVITTE_DEBUG |
339 | struct tm *lcl; | 222 | fprintf(stderr, "LEVITTE_DEBUG: | 0x%p -> 0x%p (%d)\n", str, ret, num); |
340 | #endif | 223 | #endif |
224 | if (realloc_debug_func != NULL) | ||
225 | realloc_debug_func(str, ret, num, file, line, 1); | ||
341 | 226 | ||
342 | if(m->addr == (char *)l->bio) | 227 | return ret; |
343 | return; | ||
344 | |||
345 | #ifdef CRYPTO_MDEBUG_TIME | ||
346 | lcl = localtime(&m->time); | ||
347 | #endif | ||
348 | |||
349 | sprintf(buf, | ||
350 | #ifdef CRYPTO_MDEBUG_TIME | ||
351 | "[%02d:%02d:%02d] " | ||
352 | #endif | ||
353 | "%5lu file=%s, line=%d, " | ||
354 | #ifdef CRYPTO_MDEBUG_THREAD | ||
355 | "thread=%lu, " | ||
356 | #endif | ||
357 | "number=%d, address=%08lX\n", | ||
358 | #ifdef CRYPTO_MDEBUG_TIME | ||
359 | lcl->tm_hour,lcl->tm_min,lcl->tm_sec, | ||
360 | #endif | ||
361 | m->order,m->file,m->line, | ||
362 | #ifdef CRYPTO_MDEBUG_THREAD | ||
363 | m->thread, | ||
364 | #endif | ||
365 | m->num,(unsigned long)m->addr); | ||
366 | |||
367 | BIO_puts(l->bio,buf); | ||
368 | l->chunks++; | ||
369 | l->bytes+=m->num; | ||
370 | } | 228 | } |
371 | 229 | ||
372 | void CRYPTO_mem_leaks(BIO *b) | 230 | void CRYPTO_free(void *str) |
373 | { | 231 | { |
374 | MEM_LEAK ml; | 232 | if (free_debug_func != NULL) |
375 | char buf[80]; | 233 | free_debug_func(str, 0); |
376 | 234 | #ifdef LEVITTE_DEBUG | |
377 | if (mh == NULL) return; | 235 | fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str); |
378 | ml.bio=b; | ||
379 | ml.bytes=0; | ||
380 | ml.chunks=0; | ||
381 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | ||
382 | lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml); | ||
383 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
384 | if (ml.chunks != 0) | ||
385 | { | ||
386 | sprintf(buf,"%ld bytes leaked in %d chunks\n", | ||
387 | ml.bytes,ml.chunks); | ||
388 | BIO_puts(b,buf); | ||
389 | } | ||
390 | |||
391 | #if 0 | ||
392 | lh_stats_bio(mh,b); | ||
393 | lh_node_stats_bio(mh,b); | ||
394 | lh_node_usage_stats_bio(mh,b); | ||
395 | #endif | 236 | #endif |
237 | free_func(str); | ||
238 | if (free_debug_func != NULL) | ||
239 | free_debug_func(NULL, 1); | ||
396 | } | 240 | } |
397 | 241 | ||
398 | static void (*mem_cb)()=NULL; | 242 | void *CRYPTO_remalloc(void *a, int num, const char *file, int line) |
399 | |||
400 | static void cb_leak(MEM *m, char *cb) | ||
401 | { | 243 | { |
402 | void (*mem_callback)()=(void (*)())cb; | 244 | if (a != NULL) Free(a); |
403 | mem_callback(m->order,m->file,m->line,m->num,m->addr); | 245 | a=(char *)Malloc(num); |
246 | return(a); | ||
404 | } | 247 | } |
405 | 248 | ||
406 | void CRYPTO_mem_leaks_cb(void (*cb)()) | 249 | |
250 | void CRYPTO_set_mem_debug_options(long bits) | ||
407 | { | 251 | { |
408 | if (mh == NULL) return; | 252 | if (set_debug_options_func != NULL) |
409 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | 253 | set_debug_options_func(bits); |
410 | mem_cb=cb; | ||
411 | lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb); | ||
412 | mem_cb=NULL; | ||
413 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | ||
414 | } | 254 | } |
415 | 255 | ||
416 | #ifndef NO_FP_API | 256 | long CRYPTO_get_mem_debug_options(void) |
417 | void CRYPTO_mem_leaks_fp(FILE *fp) | ||
418 | { | 257 | { |
419 | BIO *b; | 258 | if (get_debug_options_func != NULL) |
420 | 259 | return get_debug_options_func(); | |
421 | if (mh == NULL) return; | 260 | return 0; |
422 | if ((b=BIO_new(BIO_s_file())) == NULL) | ||
423 | return; | ||
424 | BIO_set_fp(b,fp,BIO_NOCLOSE); | ||
425 | CRYPTO_mem_leaks(b); | ||
426 | BIO_free(b); | ||
427 | } | 261 | } |
428 | #endif | ||
429 | |||