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