]> git.sur5r.net Git - openldap/blob - libraries/liblber/memory.c
Rebuild
[openldap] / libraries / liblber / memory.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 #include "portable.h"
7
8 #include <ac/stdlib.h>
9 #include <ac/string.h>
10
11 #include "lber-int.h"
12
13 #ifdef LDAP_MEMORY_TRACE
14 # ifndef LDAP_MEMORY_DEBUG
15 #  define LDAP_MEMORY_DEBUG 1
16 # endif
17 #include <stdio.h>
18 #endif
19
20 #if LDAP_MEMORY_DEBUG
21 /*
22  * LDAP_MEMORY_DEBUG should only be enabled for the purposes of
23  * debugging memory management within OpenLDAP libraries and slapd.
24  * It should only be enabled by an experienced developer as it
25  * causes the inclusion of numerous assert()'s, many of which may
26  * be triggered by a prefectly valid program.
27  *
28  * The code behind this macro is subject to change as needed to
29  * support this testing.
30  */
31
32 struct ber_mem_hdr {
33         ber_int_t       bm_top; /* Pattern to detect buf overrun from prev buffer */
34         ber_int_t       bm_length; /* Length of user allocated area */
35 #ifdef LDAP_MEMORY_TRACE
36         ber_int_t       bm_sequence; /* Allocation sequence number */
37 #endif
38         union bmu_align_u {     /* Force alignment, pattern to detect back clobber */
39                 ber_len_t       bmu_len_t;
40                 ber_tag_t       bmu_tag_t;
41                 ber_int_t       bmu_int_t;
42
43                 size_t  bmu_size_t;
44                 void *  bmu_voidp;
45                 double  bmu_double;
46                 long    bmu_long;
47                 long    (*bmu_funcp)( double );
48                 unsigned char   bmu_char[4];
49         } ber_align;
50 #define bm_junk ber_align.bmu_len_t
51 #define bm_data ber_align.bmu_char[1]
52 #define bm_char ber_align.bmu_char
53 };
54
55 /* Pattern at top of allocated space */
56 #define BER_MEM_JUNK 0xdeaddadaU
57
58 static const struct ber_mem_hdr ber_int_mem_hdr = { BER_MEM_JUNK, 0, 0 };
59
60 /* Note sequence and ber_int_options.lbu_meminuse are counters, but are not
61  * thread safe.  If you want to use these values for multithreaded applications,
62  * you must put mutexes around them, otherwise they will have incorrect values.
63  * When debugging, if you sort the debug output, the sequence number will 
64  * put allocations/frees together.  It is then a simple matter to write a script
65  * to find any allocations that don't have a buffer free function.
66  */
67 #ifdef LDAP_MEMORY_TRACE
68 static ber_int_t sequence = 0;
69 #endif
70
71 /* Pattern placed just before user data */
72 static unsigned char toppattern[4] = { 0xde, 0xad, 0xba, 0xde };
73 /* Pattern placed just after user data */
74 static unsigned char endpattern[4] = { 0xd1, 0xed, 0xde, 0xca };
75
76 #define mbu_len sizeof(ber_int_mem_hdr.ber_align)
77
78 /* Test if pattern placed just before user data is good */
79 #define testdatatop(val) ( \
80         *(val->bm_char+mbu_len-4)==toppattern[0] && \
81         *(val->bm_char+mbu_len-3)==toppattern[1] && \
82         *(val->bm_char+mbu_len-2)==toppattern[2] && \
83         *(val->bm_char+mbu_len-1)==toppattern[3] )
84
85 /* Place pattern just before user data */
86 #define setdatatop(val) *(val->bm_char+mbu_len-4)=toppattern[0]; \
87         *(val->bm_char+mbu_len-3)=toppattern[1]; \
88         *(val->bm_char+mbu_len-2)=toppattern[2]; \
89         *(val->bm_char+mbu_len-1)=toppattern[3];
90
91 /* Test if pattern placed just after user data is good */
92 #define testend(val) (  *((unsigned char *)val+0)==endpattern[0] && \
93         *((unsigned char *)val+1)==endpattern[1] && \
94         *((unsigned char *)val+2)==endpattern[2] && \
95         *((unsigned char *)val+3)==endpattern[3] )
96
97 /* Place pattern just after user data */
98 #define setend(val)     *((unsigned char *)val+0)=endpattern[0]; \
99         *((unsigned char *)val+1)=endpattern[1]; \
100         *((unsigned char *)val+2)=endpattern[2]; \
101         *((unsigned char *)val+3)=endpattern[3];
102
103 #define BER_MEM_BADADDR ((void *) &ber_int_mem_hdr.bm_data)
104 #define BER_MEM_VALID(p)        do { \
105                 assert( (p) != BER_MEM_BADADDR );       \
106                 assert( (p) != (void *) &ber_int_mem_hdr );     \
107         } while(0)
108
109 #else
110 #define BER_MEM_VALID(p)        /* no-op */
111 #endif
112
113 BerMemoryFunctions *ber_int_memory_fns = NULL;
114
115 #if 0 && defined( LDAP_MEMORY_DEBUG )
116 void
117 ber_int_memfree( void **p )
118 {
119         assert( p != NULL );
120         BER_MEM_VALID( *p );
121
122         ber_memfree( p );
123
124         *p = BER_MEM_BADADDR;
125 }
126 #endif
127
128 void
129 ber_memfree( void *p )
130 {
131     ber_int_options.lbo_valid = LBER_INITIALIZED;
132
133         if( p == NULL ) {
134                 return;
135         }
136
137         BER_MEM_VALID( p );
138
139         if( ber_int_memory_fns == NULL ) {
140 #ifdef LDAP_MEMORY_DEBUG
141                 struct ber_mem_hdr *mh = (struct ber_mem_hdr *)
142                         ((char *)p - sizeof(struct ber_mem_hdr));
143                 assert( mh->bm_top == BER_MEM_JUNK);
144                 assert( testdatatop( mh));
145                 assert( testend( (char *)&mh[1] + mh->bm_length) );
146                 ber_int_options.lbo_meminuse -= mh->bm_length;
147
148 #ifdef LDAP_MEMORY_TRACE
149                 fprintf(stderr, "0x%08x 0x%08x -f- %d ber_memfree %d\n",
150                         mh->bm_sequence, mh, mh->bm_length, ber_int_options.lbo_meminuse);
151 #endif
152                 /* Fill the free space with poison */
153                 memset( mh, 0xff, mh->bm_length + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t));
154                 free( mh );
155 #else
156                 free( p );
157 #endif
158                 return;
159         }
160
161         assert( ber_int_memory_fns->bmf_free );
162
163         (*ber_int_memory_fns->bmf_free)( p );
164 }
165
166
167 void
168 ber_memvfree( void **vec )
169 {
170         int     i;
171
172     ber_int_options.lbo_valid = LBER_INITIALIZED;
173
174         if( vec == NULL ) {
175                 return;
176         }
177
178         BER_MEM_VALID( vec );
179
180         for ( i = 0; vec[i] != NULL; i++ ) {
181                 LBER_FREE( vec[i] );
182         }
183
184         LBER_FREE( vec );
185 }
186
187
188 void *
189 ber_memalloc( ber_len_t s )
190 {
191         void *new;
192     ber_int_options.lbo_valid = LBER_INITIALIZED;
193
194 #ifdef LDAP_MEMORY_DEBUG
195         assert( s != 0 );
196 #endif
197
198         if( s == 0 ) {
199                 return NULL;
200         }
201
202         if( ber_int_memory_fns == NULL ) {
203 #ifdef LDAP_MEMORY_DEBUG
204                 struct ber_mem_hdr *mh = malloc(s + sizeof(struct ber_mem_hdr) + sizeof( ber_int_t));
205                 if( mh == NULL ) return NULL;
206
207                 mh->bm_top = BER_MEM_JUNK;
208                 mh->bm_length = s;
209                 setdatatop( mh);
210                 setend( (char *)&mh[1] + mh->bm_length );
211
212                 ber_int_options.lbo_meminuse += mh->bm_length;  /* Count mem inuse */
213
214 #ifdef LDAP_MEMORY_TRACE
215                 mh->bm_sequence = sequence++;
216                 fprintf(stderr, "0x%08x 0x%08x -a- %d ber_memalloc %d\n",
217                         mh->bm_sequence, mh, mh->bm_length, ber_int_options.lbo_meminuse);
218 #endif
219                 /* poison new memory */
220                 memset( (char *)&mh[1], 0xff, s);
221
222                 BER_MEM_VALID( &mh[1] );
223                 new = &mh[1];
224 #else
225                 new = malloc( s );
226 #endif
227         } else {
228                 new = (*ber_int_memory_fns->bmf_malloc)( s );
229         }
230
231         if( new == NULL ) {
232                 ber_errno = LBER_ERROR_MEMORY;
233         }
234
235         return new;
236 }
237
238
239 void *
240 ber_memcalloc( ber_len_t n, ber_len_t s )
241 {
242         void *new;
243     ber_int_options.lbo_valid = LBER_INITIALIZED;
244
245 #ifdef LDAP_MEMORY_DEBUG
246         assert( n != 0 && s != 0);
247 #endif
248
249         if( n == 0 || s == 0 ) {
250                 return NULL;
251         }
252
253         if( ber_int_memory_fns == NULL ) {
254 #ifdef LDAP_MEMORY_DEBUG
255                 struct ber_mem_hdr *mh = calloc(1,
256                         (n * s) + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) );
257                 if( mh == NULL ) return NULL;
258
259                 mh->bm_top = BER_MEM_JUNK;
260                 mh->bm_length = n*s;
261                 setdatatop( mh);
262                 setend( (char *)&mh[1] + mh->bm_length );
263
264                 ber_int_options.lbo_meminuse += mh->bm_length;
265
266 #ifdef LDAP_MEMORY_TRACE
267                 mh->bm_sequence = sequence++;
268                 fprintf(stderr, "0x%08x 0x%08x -a- %d ber_memcalloc %d\n",
269                         mh->bm_sequence, mh, mh->bm_length, ber_int_options.lbo_meminuse);
270 #endif
271                 BER_MEM_VALID( &mh[1] );
272                 new = &mh[1];
273 #else
274                 new = calloc( n, s );
275 #endif
276
277         } else {
278                 new = (*ber_int_memory_fns->bmf_calloc)( n, s );
279         }
280
281         if( new == NULL ) {
282                 ber_errno = LBER_ERROR_MEMORY;
283         }
284
285         return new;
286 }
287
288
289 void *
290 ber_memrealloc( void* p, ber_len_t s )
291 {
292         void *new = NULL;
293     ber_int_options.lbo_valid = LBER_INITIALIZED;
294
295         /* realloc(NULL,s) -> malloc(s) */
296         if( p == NULL ) {
297                 return ber_memalloc( s );
298         }
299         
300         /* realloc(p,0) -> free(p) */
301         if( s == 0 ) {
302                 ber_memfree( p );
303                 return NULL;
304         }
305
306         BER_MEM_VALID( p );
307
308         if( ber_int_memory_fns == NULL ) {
309 #ifdef LDAP_MEMORY_DEBUG
310                 ber_int_t oldlen;
311                 struct ber_mem_hdr *mh = (struct ber_mem_hdr *)
312                         ((char *)p - sizeof(struct ber_mem_hdr));
313                 assert( mh->bm_top == BER_MEM_JUNK);
314                 assert( testdatatop( mh));
315                 assert( testend( (char *)&mh[1] + mh->bm_length) );
316                 oldlen = mh->bm_length;
317
318                 p = realloc( mh, s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) );
319                 if( p == NULL ) {
320                         ber_errno = LBER_ERROR_MEMORY;
321                         return NULL;
322                 }
323
324                         mh = p;
325                 mh->bm_length = s;
326                 setend( (char *)&mh[1] + mh->bm_length );
327                 if( (s - oldlen) > 0 ) {
328                         /* poison any new memory */
329                         memset( (char *)&mh[1] + oldlen, 0xff, s - oldlen);
330                 }
331
332                 assert( mh->bm_top == BER_MEM_JUNK);
333                 assert( testdatatop( mh));
334
335                 ber_int_options.lbo_meminuse += s - oldlen;
336 #ifdef LDAP_MEMORY_TRACE
337                 fprintf(stderr, "0x%08x 0x%08x -a- %d ber_memrealloc %d\n",
338                         mh->bm_sequence, mh, mh->bm_length, ber_int_options.lbo_meminuse);
339 #endif
340                         BER_MEM_VALID( &mh[1] );
341                 return &mh[1];
342 #else
343                 new = realloc( p, s );
344 #endif
345         } else {
346                 new = (*ber_int_memory_fns->bmf_realloc)( p, s );
347         }
348
349         if( new == NULL ) {
350                 ber_errno = LBER_ERROR_MEMORY;
351         }
352
353         return new;
354 }
355
356
357 void
358 ber_bvfree( struct berval *bv )
359 {
360         ber_int_options.lbo_valid = LBER_INITIALIZED;
361
362         if( bv == NULL ) {
363                 return;
364         }
365
366         BER_MEM_VALID( bv );
367
368         if ( bv->bv_val != NULL ) {
369                 LBER_FREE( bv->bv_val );
370         }
371
372         LBER_FREE( (char *) bv );
373 }
374
375
376 void
377 ber_bvecfree( struct berval **bv )
378 {
379         int     i;
380
381         ber_int_options.lbo_valid = LBER_INITIALIZED;
382
383         if( bv == NULL ) {
384                 return;
385         }
386
387         BER_MEM_VALID( bv );
388
389         for ( i = 0; bv[i] != NULL; i++ ) {
390                 ber_bvfree( bv[i] );
391         }
392
393         LBER_FREE( (char *) bv );
394 }
395
396 int
397 ber_bvecadd( struct berval ***bvec, struct berval *bv )
398 {
399         ber_len_t i;
400         struct berval **new;
401
402         ber_int_options.lbo_valid = LBER_INITIALIZED;
403
404         if( bvec == NULL ) {
405                 if( bv == NULL ) {
406                         /* nothing to add */
407                         return 0;
408                 }
409
410                 *bvec = ber_memalloc( 2 * sizeof(struct berval *) );
411
412                 if( *bvec == NULL ) {
413                         return -1;
414                 }
415
416                 (*bvec)[0] = bv;
417                 (*bvec)[1] = NULL;
418
419                 return 1;
420         }
421
422         BER_MEM_VALID( bvec );
423
424         /* count entries */
425         for ( i = 0; bvec[i] != NULL; i++ ) {
426                 /* EMPTY */;
427         }
428
429         if( bv == NULL ) {
430                 return i;
431         }
432
433         new = ber_memrealloc( *bvec, (i+2) * sizeof(struct berval *));
434
435         if( new == NULL ) {
436                 return -1;
437         }
438
439         *bvec = new;
440
441         (*bvec)[i++] = bv;
442         (*bvec)[i] = NULL;
443
444         return i;
445 }
446
447
448 struct berval *
449 ber_bvdup(
450         LDAP_CONST struct berval *bv )
451 {
452         struct berval *new;
453
454         ber_int_options.lbo_valid = LBER_INITIALIZED;
455
456         if( bv == NULL ) {
457                 ber_errno = LBER_ERROR_PARAM;
458                 return NULL;
459         }
460
461         if(( new = LBER_MALLOC( sizeof(struct berval) )) == NULL ) {
462                 ber_errno = LBER_ERROR_MEMORY;
463                 return NULL;
464         }
465
466         if ( bv->bv_val == NULL ) {
467                 new->bv_val = NULL;
468                 new->bv_len = 0;
469                 return new;
470         }
471
472         if(( new->bv_val = LBER_MALLOC( bv->bv_len + 1 )) == NULL ) {
473                 ber_errno = LBER_ERROR_MEMORY;
474                 LBER_FREE( new );
475                 return NULL;
476         }
477
478         AC_MEMCPY( new->bv_val, bv->bv_val, bv->bv_len );
479         new->bv_val[bv->bv_len] = '\0';
480         new->bv_len = bv->bv_len;
481
482         return new;
483 }
484
485 struct berval *
486 ber_bvstr(
487         LDAP_CONST char *s )
488 {
489         struct berval *new;
490
491         ber_int_options.lbo_valid = LBER_INITIALIZED;
492
493         if( s == NULL ) {
494                 ber_errno = LBER_ERROR_PARAM;
495                 return NULL;
496         }
497
498         if(( new = LBER_MALLOC( sizeof(struct berval) )) == NULL ) {
499                 ber_errno = LBER_ERROR_MEMORY;
500                 return NULL;
501         }
502
503         new->bv_val = (char *) s;
504         new->bv_len = strlen( s );
505
506         return( new );
507 }
508
509 struct berval *
510 ber_bvstrdup(
511         LDAP_CONST char *s )
512 {
513         struct berval *new;
514         char *p;
515
516         ber_int_options.lbo_valid = LBER_INITIALIZED;
517
518         if( s == NULL ) {
519                 ber_errno = LBER_ERROR_PARAM;
520                 return NULL;
521         }
522
523         p = LBER_STRDUP( s );
524
525         if( p == NULL ) {
526                 ber_errno = LBER_ERROR_MEMORY;
527                 return NULL;
528         }
529
530         new = ber_bvstr( p );
531
532         if( new == NULL || *p == '\0' ) {
533                 LBER_FREE( p );
534         }
535
536         return new;
537 }
538
539 char *
540 ber_strdup( LDAP_CONST char *s )
541 {
542         char    *p;
543         size_t  len;
544         
545         ber_int_options.lbo_valid = LBER_INITIALIZED;
546
547 #ifdef LDAP_MEMORY_DEBUG
548         assert(s != NULL);                      /* bv damn better point to something */
549 #endif
550
551         if( s == NULL ) {
552                 ber_errno = LBER_ERROR_PARAM;
553                 return NULL;
554         }
555
556         len = strlen( s ) + 1;
557
558         if ( (p = LBER_MALLOC( len )) == NULL ) {
559                 ber_errno = LBER_ERROR_MEMORY;
560                 return NULL;
561         }
562
563         AC_MEMCPY( p, s, len );
564         return p;
565 }