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