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