Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/liblber/memory.c
4394 views
1
/* $OpenLDAP$ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
*
4
* Copyright 1998-2024 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
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
163
ber_memfree( void *p )
164
{
165
ber_memfree_x(p, NULL);
166
}
167
168
void
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
187
ber_memvfree( void **vec )
188
{
189
ber_memvfree_x( vec, NULL );
190
}
191
192
void *
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 *
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
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 *
298
ber_memcalloc( ber_len_t n, ber_len_t s )
299
{
300
return ber_memcalloc_x( n, s, NULL );
301
}
302
303
void *
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 *
371
ber_memrealloc( void* p, ber_len_t s )
372
{
373
return ber_memrealloc_x( p, s, NULL );
374
}
375
376
void
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
393
ber_bvfree( struct berval *bv )
394
{
395
ber_bvfree_x( bv, NULL );
396
}
397
398
void
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
421
ber_bvecfree( struct berval **bv )
422
{
423
ber_bvecfree_x( bv, NULL );
424
}
425
426
int
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
476
ber_bvecadd( struct berval ***bvec, struct berval *bv )
477
{
478
return ber_bvecadd_x( bvec, bv, NULL );
479
}
480
481
struct berval *
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
if ( src->bv_val == NULL ) {
494
tmp.bv_val = NULL;
495
tmp.bv_len = 0;
496
} else {
497
498
if(( tmp.bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) {
499
return NULL;
500
}
501
502
AC_MEMCPY( tmp.bv_val, src->bv_val, src->bv_len );
503
tmp.bv_val[src->bv_len] = '\0';
504
tmp.bv_len = src->bv_len;
505
}
506
*dst = tmp;
507
return dst;
508
} else {
509
if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
510
return NULL;
511
}
512
513
if ( src->bv_val == NULL ) {
514
new->bv_val = NULL;
515
new->bv_len = 0;
516
} else {
517
518
if(( new->bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) {
519
return NULL;
520
}
521
522
AC_MEMCPY( new->bv_val, src->bv_val, src->bv_len );
523
new->bv_val[src->bv_len] = '\0';
524
new->bv_len = src->bv_len;
525
}
526
return new;
527
}
528
}
529
530
struct berval *
531
ber_dupbv(
532
struct berval *dst, struct berval *src )
533
{
534
return ber_dupbv_x( dst, src, NULL );
535
}
536
537
struct berval *
538
ber_bvdup(
539
struct berval *src )
540
{
541
return ber_dupbv_x( NULL, src, NULL );
542
}
543
544
struct berval *
545
ber_str2bv_x(
546
LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
547
void *ctx)
548
{
549
struct berval *new;
550
551
if( s == NULL ) {
552
ber_errno = LBER_ERROR_PARAM;
553
return NULL;
554
}
555
556
if( bv ) {
557
new = bv;
558
} else {
559
if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
560
return NULL;
561
}
562
}
563
564
new->bv_len = len ? len : strlen( s );
565
if ( dup ) {
566
if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
567
if ( !bv )
568
ber_memfree_x( new, ctx );
569
return NULL;
570
}
571
572
AC_MEMCPY( new->bv_val, s, new->bv_len );
573
new->bv_val[new->bv_len] = '\0';
574
} else {
575
new->bv_val = (char *) s;
576
}
577
578
return( new );
579
}
580
581
struct berval *
582
ber_str2bv(
583
LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
584
{
585
return ber_str2bv_x( s, len, dup, bv, NULL );
586
}
587
588
struct berval *
589
ber_mem2bv_x(
590
LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
591
void *ctx)
592
{
593
struct berval *new;
594
595
if( s == NULL ) {
596
ber_errno = LBER_ERROR_PARAM;
597
return NULL;
598
}
599
600
if( bv ) {
601
new = bv;
602
} else {
603
if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
604
return NULL;
605
}
606
}
607
608
new->bv_len = len;
609
if ( dup ) {
610
if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
611
if ( !bv ) {
612
ber_memfree_x( new, ctx );
613
}
614
return NULL;
615
}
616
617
AC_MEMCPY( new->bv_val, s, new->bv_len );
618
new->bv_val[new->bv_len] = '\0';
619
} else {
620
new->bv_val = (char *) s;
621
}
622
623
return( new );
624
}
625
626
struct berval *
627
ber_mem2bv(
628
LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
629
{
630
return ber_mem2bv_x( s, len, dup, bv, NULL );
631
}
632
633
char *
634
ber_strdup_x( LDAP_CONST char *s, void *ctx )
635
{
636
char *p;
637
size_t len;
638
639
#ifdef LDAP_MEMORY_DEBUG
640
assert(s != NULL); /* bv damn better point to something */
641
#endif
642
643
if( s == NULL ) {
644
ber_errno = LBER_ERROR_PARAM;
645
return NULL;
646
}
647
648
len = strlen( s ) + 1;
649
if ( (p = ber_memalloc_x( len, ctx )) != NULL ) {
650
AC_MEMCPY( p, s, len );
651
}
652
653
return p;
654
}
655
656
char *
657
ber_strdup( LDAP_CONST char *s )
658
{
659
return ber_strdup_x( s, NULL );
660
}
661
662
ber_len_t
663
ber_strnlen( LDAP_CONST char *s, ber_len_t len )
664
{
665
ber_len_t l;
666
667
for ( l = 0; l < len && s[l] != '\0'; l++ ) ;
668
669
return l;
670
}
671
672
char *
673
ber_strndup_x( LDAP_CONST char *s, ber_len_t l, void *ctx )
674
{
675
char *p;
676
size_t len;
677
678
#ifdef LDAP_MEMORY_DEBUG
679
assert(s != NULL); /* bv damn better point to something */
680
#endif
681
682
if( s == NULL ) {
683
ber_errno = LBER_ERROR_PARAM;
684
return NULL;
685
}
686
687
len = ber_strnlen( s, l );
688
if ( (p = ber_memalloc_x( len + 1, ctx )) != NULL ) {
689
AC_MEMCPY( p, s, len );
690
p[len] = '\0';
691
}
692
693
return p;
694
}
695
696
char *
697
ber_strndup( LDAP_CONST char *s, ber_len_t l )
698
{
699
return ber_strndup_x( s, l, NULL );
700
}
701
702
/*
703
* dst is resized as required by src and the value of src is copied into dst
704
* dst->bv_val must be NULL (and dst->bv_len must be 0), or it must be
705
* alloc'ed with the context ctx
706
*/
707
struct berval *
708
ber_bvreplace_x( struct berval *dst, LDAP_CONST struct berval *src, void *ctx )
709
{
710
assert( dst != NULL );
711
assert( !BER_BVISNULL( src ) );
712
713
if ( BER_BVISNULL( dst ) || dst->bv_len < src->bv_len ) {
714
dst->bv_val = ber_memrealloc_x( dst->bv_val, src->bv_len + 1, ctx );
715
}
716
717
AC_MEMCPY( dst->bv_val, src->bv_val, src->bv_len + 1 );
718
dst->bv_len = src->bv_len;
719
720
return dst;
721
}
722
723
struct berval *
724
ber_bvreplace( struct berval *dst, LDAP_CONST struct berval *src )
725
{
726
return ber_bvreplace_x( dst, src, NULL );
727
}
728
729
void
730
ber_bvarray_free_x( BerVarray a, void *ctx )
731
{
732
int i;
733
734
if (a) {
735
BER_MEM_VALID( a );
736
737
/* count elements */
738
for (i=0; a[i].bv_val; i++) ;
739
740
/* free in reverse order */
741
for (i--; i>=0; i--) {
742
ber_memfree_x(a[i].bv_val, ctx);
743
}
744
745
ber_memfree_x(a, ctx);
746
}
747
}
748
749
void
750
ber_bvarray_free( BerVarray a )
751
{
752
ber_bvarray_free_x(a, NULL);
753
}
754
755
int
756
ber_bvarray_dup_x( BerVarray *dst, BerVarray src, void *ctx )
757
{
758
int i, j;
759
BerVarray new;
760
761
if ( !src ) {
762
*dst = NULL;
763
return 0;
764
}
765
766
for (i=0; !BER_BVISNULL( &src[i] ); i++) ;
767
new = ber_memalloc_x(( i+1 ) * sizeof(BerValue), ctx );
768
if ( !new )
769
return -1;
770
for (j=0; j<i; j++) {
771
ber_dupbv_x( &new[j], &src[j], ctx );
772
if ( BER_BVISNULL( &new[j] )) {
773
ber_bvarray_free_x( new, ctx );
774
return -1;
775
}
776
}
777
BER_BVZERO( &new[j] );
778
*dst = new;
779
return 0;
780
}
781
782
int
783
ber_bvarray_add_x( BerVarray *a, BerValue *bv, void *ctx )
784
{
785
int n;
786
787
if ( *a == NULL ) {
788
if (bv == NULL) {
789
return 0;
790
}
791
n = 0;
792
793
*a = (BerValue *) ber_memalloc_x( 2 * sizeof(BerValue), ctx );
794
if ( *a == NULL ) {
795
return -1;
796
}
797
798
} else {
799
BerVarray atmp;
800
BER_MEM_VALID( a );
801
802
for ( n = 0; *a != NULL && (*a)[n].bv_val != NULL; n++ ) {
803
; /* just count them */
804
}
805
806
if (bv == NULL) {
807
return n;
808
}
809
810
atmp = (BerValue *) ber_memrealloc_x( (char *) *a,
811
(n + 2) * sizeof(BerValue), ctx );
812
813
if( atmp == NULL ) {
814
return -1;
815
}
816
817
*a = atmp;
818
}
819
820
(*a)[n++] = *bv;
821
(*a)[n].bv_val = NULL;
822
(*a)[n].bv_len = 0;
823
824
return n;
825
}
826
827
int
828
ber_bvarray_add( BerVarray *a, BerValue *bv )
829
{
830
return ber_bvarray_add_x( a, bv, NULL );
831
}
832
833