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