1 /* $NetBSD: memory.c,v 1.3 2021/08/14 16:14:55 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2021 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: memory.c,v 1.3 2021/08/14 16:14:55 christos Exp $");
20
21 #include "portable.h"
22
23 #include <ac/stdlib.h>
24 #include <ac/string.h>
25
26 #include "lber-int.h"
27
28 #ifdef LDAP_MEMORY_TRACE
29 #include <stdio.h>
30 #endif
31
32 #ifdef LDAP_MEMORY_DEBUG
33 /*
34 * LDAP_MEMORY_DEBUG should only be enabled for the purposes of
35 * debugging memory management within OpenLDAP libraries and slapd.
36 *
37 * It should only be enabled by an experienced developer as it causes
38 * the inclusion of numerous assert()'s, many of which may be triggered
39 * by a perfectly valid program. If LDAP_MEMORY_DEBUG & 2 is true,
40 * that includes asserts known to break both slapd and current clients.
41 *
42 * The code behind this macro is subject to change as needed to
43 * support this testing.
44 */
45
46 struct ber_mem_hdr {
47 ber_int_t bm_top; /* Pattern to detect buf overrun from prev buffer */
48 ber_int_t bm_length; /* Length of user allocated area */
49 #ifdef LDAP_MEMORY_TRACE
50 ber_int_t bm_sequence; /* Allocation sequence number */
51 #endif
52 union bmu_align_u { /* Force alignment, pattern to detect back clobber */
53 ber_len_t bmu_len_t;
54 ber_tag_t bmu_tag_t;
55 ber_int_t bmu_int_t;
56
57 size_t bmu_size_t;
58 void * bmu_voidp;
59 double bmu_double;
60 long bmu_long;
61 long (*bmu_funcp)( double );
62 unsigned char bmu_char[4];
63 } ber_align;
64 #define bm_junk ber_align.bmu_len_t
65 #define bm_data ber_align.bmu_char[1]
66 #define bm_char ber_align.bmu_char
67 };
68
69 /* Pattern at top of allocated space */
70 #define LBER_MEM_JUNK ((ber_int_t) 0xdeaddada)
71
72 static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK };
73
74 /* Note sequence and ber_int_meminuse are counters, but are not
75 * thread safe. If you want to use these values for multithreaded applications,
76 * you must put mutexes around them, otherwise they will have incorrect values.
77 * When debugging, if you sort the debug output, the sequence number will
78 * put allocations/frees together. It is then a simple matter to write a script
79 * to find any allocations that don't have a buffer free function.
80 */
81 long ber_int_meminuse = 0;
82 #ifdef LDAP_MEMORY_TRACE
83 static ber_int_t sequence = 0;
84 #endif
85
86 /* Pattern placed just before user data */
87 static unsigned char toppattern[4] = { 0xde, 0xad, 0xba, 0xde };
88 /* Pattern placed just after user data */
89 static unsigned char endpattern[4] = { 0xd1, 0xed, 0xde, 0xca };
90
91 #define mbu_len sizeof(ber_int_mem_hdr.ber_align)
92
93 /* Test if pattern placed just before user data is good */
94 #define testdatatop(val) ( \
95 *(val->bm_char+mbu_len-4)==toppattern[0] && \
96 *(val->bm_char+mbu_len-3)==toppattern[1] && \
97 *(val->bm_char+mbu_len-2)==toppattern[2] && \
98 *(val->bm_char+mbu_len-1)==toppattern[3] )
99
100 /* Place pattern just before user data */
101 #define setdatatop(val) *(val->bm_char+mbu_len-4)=toppattern[0]; \
102 *(val->bm_char+mbu_len-3)=toppattern[1]; \
103 *(val->bm_char+mbu_len-2)=toppattern[2]; \
104 *(val->bm_char+mbu_len-1)=toppattern[3];
105
106 /* Test if pattern placed just after user data is good */
107 #define testend(val) ( *((unsigned char *)val+0)==endpattern[0] && \
108 *((unsigned char *)val+1)==endpattern[1] && \
109 *((unsigned char *)val+2)==endpattern[2] && \
110 *((unsigned char *)val+3)==endpattern[3] )
111
112 /* Place pattern just after user data */
113 #define setend(val) *((unsigned char *)val+0)=endpattern[0]; \
114 *((unsigned char *)val+1)=endpattern[1]; \
115 *((unsigned char *)val+2)=endpattern[2]; \
116 *((unsigned char *)val+3)=endpattern[3];
117
118 #define BER_MEM_BADADDR ((void *) &ber_int_mem_hdr.bm_data)
119 #define BER_MEM_VALID(p) do { \
120 assert( (p) != BER_MEM_BADADDR ); \
121 assert( (p) != (void *) &ber_int_mem_hdr ); \
122 } while(0)
123
124 #else
125 #define BER_MEM_VALID(p) /* no-op */
126 #endif
127
128 BerMemoryFunctions *ber_int_memory_fns = NULL;
129
130 void
ber_memfree_x(void * p,void * ctx)131 ber_memfree_x( void *p, void *ctx )
132 {
133 if( p == NULL ) {
134 return;
135 }
136
137 BER_MEM_VALID( p );
138
139 if( ber_int_memory_fns == NULL || ctx == 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 == LBER_MEM_JUNK);
144 assert( testdatatop( mh));
145 assert( testend( (char *)&mh[1] + mh->bm_length) );
146 ber_int_meminuse -= mh->bm_length;
147
148 #ifdef LDAP_MEMORY_TRACE
149 fprintf(stderr, "0x%08lx 0x%08lx -f- %ld ber_memfree %ld\n",
150 (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
151 ber_int_meminuse);
152 #endif
153 /* Fill the free space with poison */
154 memset( mh, 0xff, mh->bm_length + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t));
155 free( mh );
156 #else
157 free( p );
158 #endif
159 return;
160 }
161
162 assert( ber_int_memory_fns->bmf_free != 0 );
163
164 (*ber_int_memory_fns->bmf_free)( p, ctx );
165 }
166
167 void
ber_memfree(void * p)168 ber_memfree( void *p )
169 {
170 ber_memfree_x(p, NULL);
171 }
172
173 void
ber_memvfree_x(void ** vec,void * ctx)174 ber_memvfree_x( void **vec, void *ctx )
175 {
176 int i;
177
178 if( vec == NULL ) {
179 return;
180 }
181
182 BER_MEM_VALID( vec );
183
184 for ( i = 0; vec[i] != NULL; i++ ) {
185 ber_memfree_x( vec[i], ctx );
186 }
187
188 ber_memfree_x( vec, ctx );
189 }
190
191 void
ber_memvfree(void ** vec)192 ber_memvfree( void **vec )
193 {
194 ber_memvfree_x( vec, NULL );
195 }
196
197 void *
ber_memalloc_x(ber_len_t s,void * ctx)198 ber_memalloc_x( ber_len_t s, void *ctx )
199 {
200 void *new;
201
202 if( s == 0 ) {
203 LDAP_MEMORY_DEBUG_ASSERT( s != 0 );
204 return NULL;
205 }
206
207 if( ber_int_memory_fns == NULL || ctx == NULL ) {
208 #ifdef LDAP_MEMORY_DEBUG
209 new = malloc(s + sizeof(struct ber_mem_hdr) + sizeof( ber_int_t));
210 if( new )
211 {
212 struct ber_mem_hdr *mh = new;
213 mh->bm_top = LBER_MEM_JUNK;
214 mh->bm_length = s;
215 setdatatop( mh);
216 setend( (char *)&mh[1] + mh->bm_length );
217
218 ber_int_meminuse += mh->bm_length; /* Count mem inuse */
219
220 #ifdef LDAP_MEMORY_TRACE
221 mh->bm_sequence = sequence++;
222 fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memalloc %ld\n",
223 (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
224 ber_int_meminuse);
225 #endif
226 /* poison new memory */
227 memset( (char *)&mh[1], 0xff, s);
228
229 BER_MEM_VALID( &mh[1] );
230 new = &mh[1];
231 }
232 #else
233 new = malloc( s );
234 #endif
235 } else {
236 new = (*ber_int_memory_fns->bmf_malloc)( s, ctx );
237 }
238
239 if( new == NULL ) {
240 ber_errno = LBER_ERROR_MEMORY;
241 }
242
243 return new;
244 }
245
246 void *
ber_memalloc(ber_len_t s)247 ber_memalloc( ber_len_t s )
248 {
249 return ber_memalloc_x( s, NULL );
250 }
251
252 void *
ber_memcalloc_x(ber_len_t n,ber_len_t s,void * ctx)253 ber_memcalloc_x( ber_len_t n, ber_len_t s, void *ctx )
254 {
255 void *new;
256
257 if( n == 0 || s == 0 ) {
258 LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0);
259 return NULL;
260 }
261
262 if( ber_int_memory_fns == NULL || ctx == NULL ) {
263 #ifdef LDAP_MEMORY_DEBUG
264 new = n < (-sizeof(struct ber_mem_hdr) - sizeof(ber_int_t)) / s
265 ? calloc(1, n*s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t))
266 : NULL;
267 if( new )
268 {
269 struct ber_mem_hdr *mh = new;
270
271 mh->bm_top = LBER_MEM_JUNK;
272 mh->bm_length = n*s;
273 setdatatop( mh);
274 setend( (char *)&mh[1] + mh->bm_length );
275
276 ber_int_meminuse += mh->bm_length;
277
278 #ifdef LDAP_MEMORY_TRACE
279 mh->bm_sequence = sequence++;
280 fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memcalloc %ld\n",
281 (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
282 ber_int_meminuse);
283 #endif
284 BER_MEM_VALID( &mh[1] );
285 new = &mh[1];
286 }
287 #else
288 new = calloc( n, s );
289 #endif
290
291 } else {
292 new = (*ber_int_memory_fns->bmf_calloc)( n, s, ctx );
293 }
294
295 if( new == NULL ) {
296 ber_errno = LBER_ERROR_MEMORY;
297 }
298
299 return new;
300 }
301
302 void *
ber_memcalloc(ber_len_t n,ber_len_t s)303 ber_memcalloc( ber_len_t n, ber_len_t s )
304 {
305 return ber_memcalloc_x( n, s, NULL );
306 }
307
308 void *
ber_memrealloc_x(void * p,ber_len_t s,void * ctx)309 ber_memrealloc_x( void* p, ber_len_t s, void *ctx )
310 {
311 void *new = NULL;
312
313 /* realloc(NULL,s) -> malloc(s) */
314 if( p == NULL ) {
315 return ber_memalloc_x( s, ctx );
316 }
317
318 /* realloc(p,0) -> free(p) */
319 if( s == 0 ) {
320 ber_memfree_x( p, ctx );
321 return NULL;
322 }
323
324 BER_MEM_VALID( p );
325
326 if( ber_int_memory_fns == NULL || ctx == NULL ) {
327 #ifdef LDAP_MEMORY_DEBUG
328 ber_int_t oldlen;
329 struct ber_mem_hdr *mh = (struct ber_mem_hdr *)
330 ((char *)p - sizeof(struct ber_mem_hdr));
331 assert( mh->bm_top == LBER_MEM_JUNK);
332 assert( testdatatop( mh));
333 assert( testend( (char *)&mh[1] + mh->bm_length) );
334 oldlen = mh->bm_length;
335
336 p = realloc( mh, s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) );
337 if( p == NULL ) {
338 ber_errno = LBER_ERROR_MEMORY;
339 return NULL;
340 }
341
342 mh = p;
343 mh->bm_length = s;
344 setend( (char *)&mh[1] + mh->bm_length );
345 if( s > oldlen ) {
346 /* poison any new memory */
347 memset( (char *)&mh[1] + oldlen, 0xff, s - oldlen);
348 }
349
350 assert( mh->bm_top == LBER_MEM_JUNK);
351 assert( testdatatop( mh));
352
353 ber_int_meminuse += s - oldlen;
354 #ifdef LDAP_MEMORY_TRACE
355 fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memrealloc %ld\n",
356 (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
357 ber_int_meminuse);
358 #endif
359 BER_MEM_VALID( &mh[1] );
360 return &mh[1];
361 #else
362 new = realloc( p, s );
363 #endif
364 } else {
365 new = (*ber_int_memory_fns->bmf_realloc)( p, s, ctx );
366 }
367
368 if( new == NULL ) {
369 ber_errno = LBER_ERROR_MEMORY;
370 }
371
372 return new;
373 }
374
375 void *
ber_memrealloc(void * p,ber_len_t s)376 ber_memrealloc( void* p, ber_len_t s )
377 {
378 return ber_memrealloc_x( p, s, NULL );
379 }
380
381 void
ber_bvfree_x(struct berval * bv,void * ctx)382 ber_bvfree_x( struct berval *bv, void *ctx )
383 {
384 if( bv == NULL ) {
385 return;
386 }
387
388 BER_MEM_VALID( bv );
389
390 if ( bv->bv_val != NULL ) {
391 ber_memfree_x( bv->bv_val, ctx );
392 }
393
394 ber_memfree_x( (char *) bv, ctx );
395 }
396
397 void
ber_bvfree(struct berval * bv)398 ber_bvfree( struct berval *bv )
399 {
400 ber_bvfree_x( bv, NULL );
401 }
402
403 void
ber_bvecfree_x(struct berval ** bv,void * ctx)404 ber_bvecfree_x( struct berval **bv, void *ctx )
405 {
406 int i;
407
408 if( bv == NULL ) {
409 return;
410 }
411
412 BER_MEM_VALID( bv );
413
414 /* count elements */
415 for ( i = 0; bv[i] != NULL; i++ ) ;
416
417 /* free in reverse order */
418 for ( i--; i >= 0; i-- ) {
419 ber_bvfree_x( bv[i], ctx );
420 }
421
422 ber_memfree_x( (char *) bv, ctx );
423 }
424
425 void
ber_bvecfree(struct berval ** bv)426 ber_bvecfree( struct berval **bv )
427 {
428 ber_bvecfree_x( bv, NULL );
429 }
430
431 int
ber_bvecadd_x(struct berval *** bvec,struct berval * bv,void * ctx)432 ber_bvecadd_x( struct berval ***bvec, struct berval *bv, void *ctx )
433 {
434 ber_len_t i;
435 struct berval **new;
436
437 if( *bvec == NULL ) {
438 if( bv == NULL ) {
439 /* nothing to add */
440 return 0;
441 }
442
443 *bvec = ber_memalloc_x( 2 * sizeof(struct berval *), ctx );
444
445 if( *bvec == NULL ) {
446 return -1;
447 }
448
449 (*bvec)[0] = bv;
450 (*bvec)[1] = NULL;
451
452 return 1;
453 }
454
455 BER_MEM_VALID( bvec );
456
457 /* count entries */
458 for ( i = 0; (*bvec)[i] != NULL; i++ ) {
459 /* EMPTY */;
460 }
461
462 if( bv == NULL ) {
463 return i;
464 }
465
466 new = ber_memrealloc_x( *bvec, (i+2) * sizeof(struct berval *), ctx);
467
468 if( new == NULL ) {
469 return -1;
470 }
471
472 *bvec = new;
473
474 (*bvec)[i++] = bv;
475 (*bvec)[i] = NULL;
476
477 return i;
478 }
479
480 int
ber_bvecadd(struct berval *** bvec,struct berval * bv)481 ber_bvecadd( struct berval ***bvec, struct berval *bv )
482 {
483 return ber_bvecadd_x( bvec, bv, NULL );
484 }
485
486 struct berval *
ber_dupbv_x(struct berval * dst,struct berval * src,void * ctx)487 ber_dupbv_x(
488 struct berval *dst, struct berval *src, void *ctx )
489 {
490 struct berval *new, tmp;
491
492 if( src == NULL ) {
493 ber_errno = LBER_ERROR_PARAM;
494 return NULL;
495 }
496
497 if ( dst ) {
498 new = &tmp;
499 } else {
500 if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
501 return NULL;
502 }
503 }
504
505 if ( src->bv_val == NULL ) {
506 new->bv_val = NULL;
507 new->bv_len = 0;
508 } else {
509
510 if(( new->bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) {
511 if ( !dst )
512 ber_memfree_x( new, ctx );
513 return NULL;
514 }
515
516 AC_MEMCPY( new->bv_val, src->bv_val, src->bv_len );
517 new->bv_val[src->bv_len] = '\0';
518 new->bv_len = src->bv_len;
519 }
520
521 if ( dst ) {
522 *dst = *new;
523 new = dst;
524 }
525
526 return new;
527 }
528
529 struct berval *
ber_dupbv(struct berval * dst,struct berval * src)530 ber_dupbv(
531 struct berval *dst, struct berval *src )
532 {
533 return ber_dupbv_x( dst, src, NULL );
534 }
535
536 struct berval *
ber_bvdup(struct berval * src)537 ber_bvdup(
538 struct berval *src )
539 {
540 return ber_dupbv_x( NULL, src, NULL );
541 }
542
543 struct berval *
ber_str2bv_x(LDAP_CONST char * s,ber_len_t len,int dup,struct berval * bv,void * ctx)544 ber_str2bv_x(
545 LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
546 void *ctx)
547 {
548 struct berval *new;
549
550 if( s == NULL ) {
551 ber_errno = LBER_ERROR_PARAM;
552 return NULL;
553 }
554
555 if( bv ) {
556 new = bv;
557 } else {
558 if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
559 return NULL;
560 }
561 }
562
563 new->bv_len = len ? len : strlen( s );
564 if ( dup ) {
565 if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
566 if ( !bv )
567 ber_memfree_x( new, ctx );
568 return NULL;
569 }
570
571 AC_MEMCPY( new->bv_val, s, new->bv_len );
572 new->bv_val[new->bv_len] = '\0';
573 } else {
574 new->bv_val = (char *) s;
575 }
576
577 return( new );
578 }
579
580 struct berval *
ber_str2bv(LDAP_CONST char * s,ber_len_t len,int dup,struct berval * bv)581 ber_str2bv(
582 LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
583 {
584 return ber_str2bv_x( s, len, dup, bv, NULL );
585 }
586
587 struct berval *
ber_mem2bv_x(LDAP_CONST char * s,ber_len_t len,int dup,struct berval * bv,void * ctx)588 ber_mem2bv_x(
589 LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
590 void *ctx)
591 {
592 struct berval *new;
593
594 if( s == NULL ) {
595 ber_errno = LBER_ERROR_PARAM;
596 return NULL;
597 }
598
599 if( bv ) {
600 new = bv;
601 } else {
602 if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
603 return NULL;
604 }
605 }
606
607 new->bv_len = len;
608 if ( dup ) {
609 if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
610 if ( !bv ) {
611 ber_memfree_x( new, ctx );
612 }
613 return NULL;
614 }
615
616 AC_MEMCPY( new->bv_val, s, new->bv_len );
617 new->bv_val[new->bv_len] = '\0';
618 } else {
619 new->bv_val = (char *) s;
620 }
621
622 return( new );
623 }
624
625 struct berval *
ber_mem2bv(LDAP_CONST char * s,ber_len_t len,int dup,struct berval * bv)626 ber_mem2bv(
627 LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
628 {
629 return ber_mem2bv_x( s, len, dup, bv, NULL );
630 }
631
632 char *
ber_strdup_x(LDAP_CONST char * s,void * ctx)633 ber_strdup_x( LDAP_CONST char *s, void *ctx )
634 {
635 char *p;
636 size_t len;
637
638 #ifdef LDAP_MEMORY_DEBUG
639 assert(s != NULL); /* bv damn better point to something */
640 #endif
641
642 if( s == NULL ) {
643 ber_errno = LBER_ERROR_PARAM;
644 return NULL;
645 }
646
647 len = strlen( s ) + 1;
648 if ( (p = ber_memalloc_x( len, ctx )) != NULL ) {
649 AC_MEMCPY( p, s, len );
650 }
651
652 return p;
653 }
654
655 char *
ber_strdup(LDAP_CONST char * s)656 ber_strdup( LDAP_CONST char *s )
657 {
658 return ber_strdup_x( s, NULL );
659 }
660
661 ber_len_t
ber_strnlen(LDAP_CONST char * s,ber_len_t len)662 ber_strnlen( LDAP_CONST char *s, ber_len_t len )
663 {
664 ber_len_t l;
665
666 for ( l = 0; l < len && s[l] != '\0'; l++ ) ;
667
668 return l;
669 }
670
671 char *
ber_strndup_x(LDAP_CONST char * s,ber_len_t l,void * ctx)672 ber_strndup_x( LDAP_CONST char *s, ber_len_t l, void *ctx )
673 {
674 char *p;
675 size_t len;
676
677 #ifdef LDAP_MEMORY_DEBUG
678 assert(s != NULL); /* bv damn better point to something */
679 #endif
680
681 if( s == NULL ) {
682 ber_errno = LBER_ERROR_PARAM;
683 return NULL;
684 }
685
686 len = ber_strnlen( s, l );
687 if ( (p = ber_memalloc_x( len + 1, ctx )) != NULL ) {
688 AC_MEMCPY( p, s, len );
689 p[len] = '\0';
690 }
691
692 return p;
693 }
694
695 char *
ber_strndup(LDAP_CONST char * s,ber_len_t l)696 ber_strndup( LDAP_CONST char *s, ber_len_t l )
697 {
698 return ber_strndup_x( s, l, NULL );
699 }
700
701 /*
702 * dst is resized as required by src and the value of src is copied into dst
703 * dst->bv_val must be NULL (and dst->bv_len must be 0), or it must be
704 * alloc'ed with the context ctx
705 */
706 struct berval *
ber_bvreplace_x(struct berval * dst,LDAP_CONST struct berval * src,void * ctx)707 ber_bvreplace_x( struct berval *dst, LDAP_CONST struct berval *src, void *ctx )
708 {
709 assert( dst != NULL );
710 assert( !BER_BVISNULL( src ) );
711
712 if ( BER_BVISNULL( dst ) || dst->bv_len < src->bv_len ) {
713 dst->bv_val = ber_memrealloc_x( dst->bv_val, src->bv_len + 1, ctx );
714 }
715
716 AC_MEMCPY( dst->bv_val, src->bv_val, src->bv_len + 1 );
717 dst->bv_len = src->bv_len;
718
719 return dst;
720 }
721
722 struct berval *
ber_bvreplace(struct berval * dst,LDAP_CONST struct berval * src)723 ber_bvreplace( struct berval *dst, LDAP_CONST struct berval *src )
724 {
725 return ber_bvreplace_x( dst, src, NULL );
726 }
727
728 void
ber_bvarray_free_x(BerVarray a,void * ctx)729 ber_bvarray_free_x( BerVarray a, void *ctx )
730 {
731 int i;
732
733 if (a) {
734 BER_MEM_VALID( a );
735
736 /* count elements */
737 for (i=0; a[i].bv_val; i++) ;
738
739 /* free in reverse order */
740 for (i--; i>=0; i--) {
741 ber_memfree_x(a[i].bv_val, ctx);
742 }
743
744 ber_memfree_x(a, ctx);
745 }
746 }
747
748 void
ber_bvarray_free(BerVarray a)749 ber_bvarray_free( BerVarray a )
750 {
751 ber_bvarray_free_x(a, NULL);
752 }
753
754 int
ber_bvarray_dup_x(BerVarray * dst,BerVarray src,void * ctx)755 ber_bvarray_dup_x( BerVarray *dst, BerVarray src, void *ctx )
756 {
757 int i, j;
758 BerVarray new;
759
760 if ( !src ) {
761 *dst = NULL;
762 return 0;
763 }
764
765 for (i=0; !BER_BVISNULL( &src[i] ); i++) ;
766 new = ber_memalloc_x(( i+1 ) * sizeof(BerValue), ctx );
767 if ( !new )
768 return -1;
769 for (j=0; j<i; j++) {
770 ber_dupbv_x( &new[j], &src[j], ctx );
771 if ( BER_BVISNULL( &new[j] )) {
772 ber_bvarray_free_x( new, ctx );
773 return -1;
774 }
775 }
776 BER_BVZERO( &new[j] );
777 *dst = new;
778 return 0;
779 }
780
781 int
ber_bvarray_add_x(BerVarray * a,BerValue * bv,void * ctx)782 ber_bvarray_add_x( BerVarray *a, BerValue *bv, void *ctx )
783 {
784 int n;
785
786 if ( *a == NULL ) {
787 if (bv == NULL) {
788 return 0;
789 }
790 n = 0;
791
792 *a = (BerValue *) ber_memalloc_x( 2 * sizeof(BerValue), ctx );
793 if ( *a == NULL ) {
794 return -1;
795 }
796
797 } else {
798 BerVarray atmp;
799 BER_MEM_VALID( a );
800
801 for ( n = 0; *a != NULL && (*a)[n].bv_val != NULL; n++ ) {
802 ; /* just count them */
803 }
804
805 if (bv == NULL) {
806 return n;
807 }
808
809 atmp = (BerValue *) ber_memrealloc_x( (char *) *a,
810 (n + 2) * sizeof(BerValue), ctx );
811
812 if( atmp == NULL ) {
813 return -1;
814 }
815
816 *a = atmp;
817 }
818
819 (*a)[n++] = *bv;
820 (*a)[n].bv_val = NULL;
821 (*a)[n].bv_len = 0;
822
823 return n;
824 }
825
826 int
ber_bvarray_add(BerVarray * a,BerValue * bv)827 ber_bvarray_add( BerVarray *a, BerValue *bv )
828 {
829 return ber_bvarray_add_x( a, bv, NULL );
830 }
831