Bug Summary

File:src/lib/libutil/ber.c
Warning:line 676, column 2
Potential leak of memory pointed to by 'ber'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ber.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libutil/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libutil/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libutil/ber.c
1/* $OpenBSD: ber.c,v 1.23 2021/10/21 08:17:33 martijn Exp $ */
2
3/*
4 * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <sys/types.h>
22
23#include <errno(*__errno()).h>
24#include <limits.h>
25#include <stdlib.h>
26#include <err.h> /* XXX for debug output */
27#include <stdio.h> /* XXX for debug output */
28#include <string.h>
29#include <unistd.h>
30#include <stdarg.h>
31
32#include "ber.h"
33
34#define BER_TYPE_CONSTRUCTED0x20 0x20 /* otherwise primitive */
35#define BER_TYPE_SINGLE_MAX30 30
36#define BER_TAG_MASK0x1f 0x1f
37#define BER_TAG_MORE0x80 0x80 /* more subsequent octets */
38#define BER_TAG_TYPE_MASK0x7f 0x7f
39#define BER_CLASS_SHIFT6 6
40
41static int ober_dump_element(struct ber *ber, struct ber_element *root);
42static void ober_dump_header(struct ber *ber, struct ber_element *root);
43static void ober_putc(struct ber *ber, u_char c);
44static void ober_write(struct ber *ber, void *buf, size_t len);
45static ssize_t get_id(struct ber *b, unsigned int *tag, int *class,
46 int *cstruct);
47static ssize_t get_len(struct ber *b, ssize_t *len);
48static ssize_t ober_read_element(struct ber *ber, struct ber_element *elm);
49static ssize_t ober_getc(struct ber *b, u_char *c);
50static ssize_t ober_read(struct ber *ber, void *buf, size_t len);
51
52#ifdef DEBUG
53#define DPRINTF(...)do { } while (0) printf(__VA_ARGS__)
54#else
55#define DPRINTF(...)do { } while (0) do { } while (0)
56#endif
57
58struct ber_element *
59ober_get_element(unsigned int encoding)
60{
61 struct ber_element *elm;
62
63 if ((elm = calloc(1, sizeof(*elm))) == NULL((void *)0))
5
Memory is allocated
6
Assuming the condition is false
7
Taking false branch
64 return NULL((void *)0);
65
66 elm->be_encoding = encoding;
67 ober_set_header(elm, BER_CLASS_UNIVERSAL0x0, BER_TYPE_DEFAULT((unsigned int)-1));
68
69 return elm;
70}
71
72void
73ober_set_header(struct ber_element *elm, int class, unsigned int type)
74{
75 elm->be_class = class & BER_CLASS_MASK0x3;
76 if (type == BER_TYPE_DEFAULT((unsigned int)-1))
77 type = elm->be_encoding;
78 elm->be_type = type;
79}
80
81void
82ober_link_elements(struct ber_element *prev, struct ber_element *elm)
83{
84 if (prev != NULL((void *)0)) {
85 if ((prev->be_encoding == BER_TYPE_SEQUENCE16 ||
86 prev->be_encoding == BER_TYPE_SET17) &&
87 prev->be_subbe_union.bv_sub == NULL((void *)0))
88 prev->be_subbe_union.bv_sub = elm;
89 else
90 prev->be_next = elm;
91 }
92}
93
94struct ber_element *
95ober_unlink_elements(struct ber_element *prev)
96{
97 struct ber_element *elm;
98
99 if ((prev->be_encoding == BER_TYPE_SEQUENCE16 ||
100 prev->be_encoding == BER_TYPE_SET17) &&
101 prev->be_subbe_union.bv_sub != NULL((void *)0)) {
102 elm = prev->be_subbe_union.bv_sub;
103 prev->be_subbe_union.bv_sub = NULL((void *)0);
104 } else {
105 elm = prev->be_next;
106 prev->be_next = NULL((void *)0);
107 }
108
109 return (elm);
110}
111
112void
113ober_replace_elements(struct ber_element *prev, struct ber_element *new)
114{
115 struct ber_element *ber, *next;
116
117 ber = ober_unlink_elements(prev);
118 next = ober_unlink_elements(ber);
119 ober_link_elements(new, next);
120 ober_link_elements(prev, new);
121
122 /* cleanup old element */
123 ober_free_elements(ber);
124}
125
126struct ber_element *
127ober_add_sequence(struct ber_element *prev)
128{
129 struct ber_element *elm;
130
131 if ((elm = ober_get_element(BER_TYPE_SEQUENCE16)) == NULL((void *)0))
132 return NULL((void *)0);
133
134 ober_link_elements(prev, elm);
135
136 return elm;
137}
138
139struct ber_element *
140ober_add_set(struct ber_element *prev)
141{
142 struct ber_element *elm;
143
144 if ((elm = ober_get_element(BER_TYPE_SET17)) == NULL((void *)0))
145 return NULL((void *)0);
146
147 ober_link_elements(prev, elm);
148
149 return elm;
150}
151
152struct ber_element *
153ober_add_enumerated(struct ber_element *prev, long long val)
154{
155 struct ber_element *elm;
156 u_int i, len = 0;
157 u_char cur, last = 0;
158
159 if ((elm = ober_get_element(BER_TYPE_ENUMERATED10)) == NULL((void *)0))
160 return NULL((void *)0);
161
162 elm->be_numericbe_union.bv_numeric = val;
163
164 for (i = 0; i < sizeof(long long); i++) {
165 cur = val & 0xff;
166 if (cur != 0 && cur != 0xff)
167 len = i;
168 if ((cur == 0 && last & 0x80) ||
169 (cur == 0xff && (last & 0x80) == 0))
170 len = i;
171 val >>= 8;
172 last = cur;
173 }
174 elm->be_len = len + 1;
175
176 ober_link_elements(prev, elm);
177
178 return elm;
179}
180
181struct ber_element *
182ober_add_integer(struct ber_element *prev, long long val)
183{
184 struct ber_element *elm;
185 u_int i, len = 0;
186 u_char cur, last = 0;
187
188 if ((elm = ober_get_element(BER_TYPE_INTEGER2)) == NULL((void *)0))
189 return NULL((void *)0);
190
191 elm->be_numericbe_union.bv_numeric = val;
192
193 for (i = 0; i < sizeof(long long); i++) {
194 cur = val & 0xff;
195 if (cur != 0 && cur != 0xff)
196 len = i;
197 if ((cur == 0 && last & 0x80) ||
198 (cur == 0xff && (last & 0x80) == 0))
199 len = i;
200 val >>= 8;
201 last = cur;
202 }
203 elm->be_len = len + 1;
204
205 ober_link_elements(prev, elm);
206
207 return elm;
208}
209
210int
211ober_get_integer(struct ber_element *elm, long long *n)
212{
213 if (elm->be_encoding != BER_TYPE_INTEGER2)
214 return -1;
215
216 if (n != NULL((void *)0))
217 *n = elm->be_numericbe_union.bv_numeric;
218 return 0;
219}
220
221int
222ober_get_enumerated(struct ber_element *elm, long long *n)
223{
224 if (elm->be_encoding != BER_TYPE_ENUMERATED10)
225 return -1;
226
227 if (n != NULL((void *)0))
228 *n = elm->be_numericbe_union.bv_numeric;
229 return 0;
230}
231
232struct ber_element *
233ober_add_boolean(struct ber_element *prev, int bool)
234{
235 struct ber_element *elm;
236
237 if ((elm = ober_get_element(BER_TYPE_BOOLEAN1)) == NULL((void *)0))
238 return NULL((void *)0);
239
240 elm->be_numericbe_union.bv_numeric = bool ? 0xff : 0;
241 elm->be_len = 1;
242
243 ober_link_elements(prev, elm);
244
245 return elm;
246}
247
248int
249ober_get_boolean(struct ber_element *elm, int *b)
250{
251 if (elm->be_encoding != BER_TYPE_BOOLEAN1)
252 return -1;
253
254 if (b != NULL((void *)0))
255 *b = !(elm->be_numericbe_union.bv_numeric == 0);
256 return 0;
257}
258
259struct ber_element *
260ober_add_string(struct ber_element *prev, const char *string)
261{
262 return ober_add_nstring(prev, string, strlen(string));
263}
264
265struct ber_element *
266ober_add_nstring(struct ber_element *prev, const char *string0, size_t len)
267{
268 struct ber_element *elm;
269 char *string;
270
271 if ((string = calloc(1, len + 1)) == NULL((void *)0))
272 return NULL((void *)0);
273 if ((elm = ober_get_element(BER_TYPE_OCTETSTRING4)) == NULL((void *)0)) {
274 free(string);
275 return NULL((void *)0);
276 }
277
278 bcopy(string0, string, len);
279 elm->be_valbe_union.bv_val = string;
280 elm->be_len = len;
281 elm->be_free = 1; /* free string on cleanup */
282
283 ober_link_elements(prev, elm);
284
285 return elm;
286}
287
288struct ber_element *
289ober_add_ostring(struct ber_element *prev, struct ber_octetstring *s)
290{
291 return ober_add_nstring(prev, s->ostr_val, s->ostr_len);
292}
293
294int
295ober_get_string(struct ber_element *elm, char **s)
296{
297 if (elm->be_encoding != BER_TYPE_OCTETSTRING4)
298 return -1;
299 /* XXX some components use getstring on binary data containing \0 */
300#if 0
301 if (memchr(elm->be_valbe_union.bv_val, '\0', elm->be_len) != NULL((void *)0))
302 return -1;
303#endif
304
305 if (s != NULL((void *)0))
306 *s = elm->be_valbe_union.bv_val;
307 return 0;
308}
309
310int
311ober_get_nstring(struct ber_element *elm, void **p, size_t *len)
312{
313 if (elm->be_encoding != BER_TYPE_OCTETSTRING4)
314 return -1;
315
316 if (len != NULL((void *)0))
317 *len = elm->be_len;
318 if (p != NULL((void *)0)) {
319 if (len != NULL((void *)0))
320 *p = elm->be_valbe_union.bv_val;
321 else
322 *p = NULL((void *)0);
323 }
324 return 0;
325}
326
327int
328ober_get_ostring(struct ber_element *elm, struct ber_octetstring *s)
329{
330 if (elm->be_encoding != BER_TYPE_OCTETSTRING4)
331 return -1;
332
333 if (s != NULL((void *)0)) {
334 s->ostr_val = elm->be_valbe_union.bv_val;
335 s->ostr_len = elm->be_len;
336 }
337 return 0;
338}
339
340struct ber_element *
341ober_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
342{
343 struct ber_element *elm;
344 void *v;
345
346 if ((v = calloc(1, len)) == NULL((void *)0))
347 return NULL((void *)0);
348 if ((elm = ober_get_element(BER_TYPE_BITSTRING3)) == NULL((void *)0)) {
349 free(v);
350 return NULL((void *)0);
351 }
352
353 bcopy(v0, v, len);
354 elm->be_valbe_union.bv_val = v;
355 elm->be_len = len;
356 elm->be_free = 1; /* free string on cleanup */
357
358 ober_link_elements(prev, elm);
359
360 return elm;
361}
362
363int
364ober_get_bitstring(struct ber_element *elm, void **v, size_t *len)
365{
366 if (elm->be_encoding != BER_TYPE_BITSTRING3)
367 return -1;
368
369 if (len != NULL((void *)0))
370 *len = elm->be_len;
371 if (v != NULL((void *)0)) {
372 if (len != NULL((void *)0))
373 *v = elm->be_valbe_union.bv_val;
374 else
375 *v = NULL((void *)0);
376 }
377 return 0;
378}
379
380struct ber_element *
381ober_add_null(struct ber_element *prev)
382{
383 struct ber_element *elm;
384
385 if ((elm = ober_get_element(BER_TYPE_NULL5)) == NULL((void *)0))
386 return NULL((void *)0);
387
388 ober_link_elements(prev, elm);
389
390 return elm;
391}
392
393int
394ober_get_null(struct ber_element *elm)
395{
396 if (elm->be_encoding != BER_TYPE_NULL5)
397 return -1;
398
399 return 0;
400}
401
402struct ber_element *
403ober_add_eoc(struct ber_element *prev)
404{
405 struct ber_element *elm;
406
407 if ((elm = ober_get_element(BER_TYPE_EOC0)) == NULL((void *)0))
4
Calling 'ober_get_element'
8
Returned allocated memory
9
Taking false branch
408 return NULL((void *)0);
409
410 ober_link_elements(prev, elm);
411
412 return elm;
413}
414
415int
416ober_get_eoc(struct ber_element *elm)
417{
418 if (elm->be_encoding != BER_TYPE_EOC0)
419 return -1;
420
421 return 0;
422}
423
424size_t
425ober_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
426{
427 u_int32_t v;
428 u_int i, j = 0, k;
429
430 if (o->bo_n < BER_MIN_OID_LEN2 || o->bo_n > BER_MAX_OID_LEN128 ||
431 o->bo_id[0] > 2 || o->bo_id[1] > 40)
432 return (0);
433
434 v = (o->bo_id[0] * 40) + o->bo_id[1];
435 for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
436 for (k = 28; k >= 7; k -= 7) {
437 if (v >= (u_int)(1 << k)) {
438 if (len)
439 buf[j] = v >> k | BER_TAG_MORE0x80;
440 j++;
441 }
442 }
443 if (len)
444 buf[j] = v & BER_TAG_TYPE_MASK0x7f;
445 j++;
446 }
447
448 return (j);
449}
450
451int
452ober_string2oid(const char *oidstr, struct ber_oid *o)
453{
454 char *sp, *p, str[BUFSIZ1024];
455 const char *errstr;
456
457 if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
458 return (-1);
459 memset(o, 0, sizeof(*o));
460
461 /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
462 for (p = sp = str; p != NULL((void *)0); sp = p) {
463 if ((p = strpbrk(p, "._-")) != NULL((void *)0))
464 *p++ = '\0';
465 o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX(2147483647 *2U +1U), &errstr);
466 if (errstr || o->bo_n > BER_MAX_OID_LEN128)
467 return (-1);
468 }
469
470 return (0);
471}
472
473int
474ober_oid_cmp(struct ber_oid *a, struct ber_oid *b)
475{
476 size_t i, min;
477
478 min = a->bo_n < b->bo_n ? a->bo_n : b->bo_n;
479 for (i = 0; i < min; i++) {
480 if (a->bo_id[i] < b->bo_id[i])
481 return (-1);
482 if (a->bo_id[i] > b->bo_id[i])
483 return (1);
484 }
485 /* a is parent of b */
486 if (a->bo_n < b->bo_n)
487 return (-2);
488 /* a is child of b */
489 if (a->bo_n > b->bo_n)
490 return 2;
491 return (0);
492}
493
494struct ber_element *
495ober_add_oid(struct ber_element *prev, struct ber_oid *o)
496{
497 struct ber_element *elm;
498 u_int8_t *buf;
499 size_t len;
500
501 if ((elm = ober_get_element(BER_TYPE_OBJECT6)) == NULL((void *)0))
502 return (NULL((void *)0));
503
504 if ((len = ober_oid2ber(o, NULL((void *)0), 0)) == 0)
505 goto fail;
506
507 if ((buf = calloc(1, len)) == NULL((void *)0))
508 goto fail;
509
510 elm->be_valbe_union.bv_val = buf;
511 elm->be_len = len;
512 elm->be_free = 1;
513
514 if (ober_oid2ber(o, buf, len) != len)
515 goto fail;
516
517 ober_link_elements(prev, elm);
518
519 return (elm);
520
521 fail:
522 ober_free_elements(elm);
523 return (NULL((void *)0));
524}
525
526struct ber_element *
527ober_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
528{
529 struct ber_oid no;
530
531 if (n > BER_MAX_OID_LEN128)
532 return (NULL((void *)0));
533 no.bo_n = n;
534 bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
535
536 return (ober_add_oid(prev, &no));
537}
538
539struct ber_element *
540ober_add_oidstring(struct ber_element *prev, const char *oidstr)
541{
542 struct ber_oid o;
543
544 if (ober_string2oid(oidstr, &o) == -1)
545 return (NULL((void *)0));
546
547 return (ober_add_oid(prev, &o));
548}
549
550int
551ober_get_oid(struct ber_element *elm, struct ber_oid *o)
552{
553 u_int8_t *buf;
554 size_t len, i = 0, j = 0;
555
556 if (elm->be_encoding != BER_TYPE_OBJECT6)
557 return (-1);
558
559 if (o == NULL((void *)0))
560 return 0;
561
562 buf = elm->be_valbe_union.bv_val;
563 len = elm->be_len;
564
565 memset(o, 0, sizeof(*o));
566 o->bo_id[j++] = buf[i] / 40;
567 o->bo_id[j++] = buf[i++] % 40;
568 for (; i < len && j < BER_MAX_OID_LEN128; i++) {
569 o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
570 if (buf[i] & 0x80)
571 continue;
572 j++;
573 }
574 o->bo_n = j;
575
576 return (0);
577}
578
579struct ber_element *
580ober_printf_elements(struct ber_element *ber, char *fmt, ...)
581{
582 va_list ap;
583 int d, class;
584 size_t len;
585 unsigned int type;
586 long long i;
587 char *s;
588 void *p;
589 struct ber_oid *o;
590 struct ber_element *sub = ber, *e;
591
592 va_start(ap, fmt)__builtin_va_start(ap, fmt);
593 while (*fmt) {
1
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
16
Loop condition is false. Execution continues on line 676
594 switch (*fmt++) {
2
Control jumps to 'case 46:' at line 667
14
Control jumps to 'case 41:' at line 664
595 case 'B':
596 p = va_arg(ap, void *)__builtin_va_arg(ap, void *);
597 len = va_arg(ap, size_t)__builtin_va_arg(ap, size_t);
598 if ((ber = ober_add_bitstring(ber, p, len)) == NULL((void *)0))
599 goto fail;
600 break;
601 case 'b':
602 d = va_arg(ap, int)__builtin_va_arg(ap, int);
603 if ((ber = ober_add_boolean(ber, d)) == NULL((void *)0))
604 goto fail;
605 break;
606 case 'd':
607 d = va_arg(ap, int)__builtin_va_arg(ap, int);
608 if ((ber = ober_add_integer(ber, d)) == NULL((void *)0))
609 goto fail;
610 break;
611 case 'e':
612 e = va_arg(ap, struct ber_element *)__builtin_va_arg(ap, struct ber_element *);
613 ober_link_elements(ber, e);
614 break;
615 case 'E':
616 i = va_arg(ap, long long)__builtin_va_arg(ap, long long);
617 if ((ber = ober_add_enumerated(ber, i)) == NULL((void *)0))
618 goto fail;
619 break;
620 case 'i':
621 i = va_arg(ap, long long)__builtin_va_arg(ap, long long);
622 if ((ber = ober_add_integer(ber, i)) == NULL((void *)0))
623 goto fail;
624 break;
625 case 'O':
626 o = va_arg(ap, struct ber_oid *)__builtin_va_arg(ap, struct ber_oid *);
627 if ((ber = ober_add_oid(ber, o)) == NULL((void *)0))
628 goto fail;
629 break;
630 case 'o':
631 s = va_arg(ap, char *)__builtin_va_arg(ap, char *);
632 if ((ber = ober_add_oidstring(ber, s)) == NULL((void *)0))
633 goto fail;
634 break;
635 case 's':
636 s = va_arg(ap, char *)__builtin_va_arg(ap, char *);
637 if ((ber = ober_add_string(ber, s)) == NULL((void *)0))
638 goto fail;
639 break;
640 case 't':
641 class = va_arg(ap, int)__builtin_va_arg(ap, int);
642 type = va_arg(ap, unsigned int)__builtin_va_arg(ap, unsigned int);
643 ober_set_header(ber, class, type);
644 break;
645 case 'x':
646 s = va_arg(ap, char *)__builtin_va_arg(ap, char *);
647 len = va_arg(ap, size_t)__builtin_va_arg(ap, size_t);
648 if ((ber = ober_add_nstring(ber, s, len)) == NULL((void *)0))
649 goto fail;
650 break;
651 case '0':
652 if ((ber = ober_add_null(ber)) == NULL((void *)0))
653 goto fail;
654 break;
655 case '{':
656 if ((ber = sub = ober_add_sequence(ber)) == NULL((void *)0))
657 goto fail;
658 break;
659 case '(':
660 if ((ber = sub = ober_add_set(ber)) == NULL((void *)0))
661 goto fail;
662 break;
663 case '}':
664 case ')':
665 ber = sub;
666 break;
15
Execution continues on line 593
667 case '.':
668 if ((e = ober_add_eoc(ber)) == NULL((void *)0))
3
Calling 'ober_add_eoc'
10
Returned allocated memory
11
Taking false branch
669 goto fail;
670 ber = e;
671 break;
12
Execution continues on line 593
672 default:
673 break;
674 }
675 }
676 va_end(ap)__builtin_va_end(ap);
17
Potential leak of memory pointed to by 'ber'
677
678 return (ber);
679 fail:
680 ober_free_elements(ber);
681 return (NULL((void *)0));
682}
683
684int
685ober_scanf_elements(struct ber_element *ber, char *fmt, ...)
686{
687#define _MAX_SEQ128 128
688 va_list ap;
689 int *d, level = -1;
690 unsigned int *t;
691 long long *i, l;
692 void **ptr;
693 size_t *len, ret = 0, n = strlen(fmt);
694 char **s;
695 off_t *pos;
696 struct ber_oid *o;
697 struct ber_element *parent[_MAX_SEQ128], **e;
698
699 memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ128);
700
701 va_start(ap, fmt)__builtin_va_start(ap, fmt);
702 while (*fmt) {
703 if (ber == NULL((void *)0) && *fmt != '$' && *fmt != '}' && *fmt != ')')
704 goto fail;
705 switch (*fmt++) {
706 case '$':
707 if (ber != NULL((void *)0))
708 goto fail;
709 ret++;
710 continue;
711 case 'B':
712 ptr = va_arg(ap, void **)__builtin_va_arg(ap, void **);
713 len = va_arg(ap, size_t *)__builtin_va_arg(ap, size_t *);
714 if (ober_get_bitstring(ber, ptr, len) == -1)
715 goto fail;
716 ret++;
717 break;
718 case 'b':
719 d = va_arg(ap, int *)__builtin_va_arg(ap, int *);
720 if (ober_get_boolean(ber, d) == -1)
721 goto fail;
722 ret++;
723 break;
724 case 'd':
725 d = va_arg(ap, int *)__builtin_va_arg(ap, int *);
726 if (ober_get_integer(ber, &l) == -1)
727 goto fail;
728 if (d != NULL((void *)0))
729 *d = l;
730 ret++;
731 break;
732 case 'e':
733 e = va_arg(ap, struct ber_element **)__builtin_va_arg(ap, struct ber_element **);
734 *e = ber;
735 ret++;
736 continue;
737 case 'E':
738 i = va_arg(ap, long long *)__builtin_va_arg(ap, long long *);
739 if (ober_get_enumerated(ber, i) == -1)
740 goto fail;
741 ret++;
742 break;
743 case 'i':
744 i = va_arg(ap, long long *)__builtin_va_arg(ap, long long *);
745 if (ober_get_integer(ber, i) == -1)
746 goto fail;
747 ret++;
748 break;
749 case 'o':
750 o = va_arg(ap, struct ber_oid *)__builtin_va_arg(ap, struct ber_oid *);
751 if (ober_get_oid(ber, o) == -1)
752 goto fail;
753 ret++;
754 break;
755 case 'S':
756 ret++;
757 break;
758 case 's':
759 s = va_arg(ap, char **)__builtin_va_arg(ap, char **);
760 if (ober_get_string(ber, s) == -1)
761 goto fail;
762 ret++;
763 break;
764 case 't':
765 d = va_arg(ap, int *)__builtin_va_arg(ap, int *);
766 t = va_arg(ap, unsigned int *)__builtin_va_arg(ap, unsigned int *);
767 if (d != NULL((void *)0))
768 *d = ber->be_class;
769 if (t != NULL((void *)0))
770 *t = ber->be_type;
771 ret++;
772 continue;
773 case 'x':
774 ptr = va_arg(ap, void **)__builtin_va_arg(ap, void **);
775 len = va_arg(ap, size_t *)__builtin_va_arg(ap, size_t *);
776 if (ober_get_nstring(ber, ptr, len) == -1)
777 goto fail;
778 ret++;
779 break;
780 case '0':
781 if (ber->be_encoding != BER_TYPE_NULL5)
782 goto fail;
783 ret++;
784 break;
785 case '.':
786 if (ber->be_encoding != BER_TYPE_EOC0)
787 goto fail;
788 ret++;
789 break;
790 case 'p':
791 pos = va_arg(ap, off_t *)__builtin_va_arg(ap, off_t *);
792 *pos = ober_getpos(ber);
793 ret++;
794 continue;
795 case '{':
796 case '(':
797 if (ber->be_encoding != BER_TYPE_SEQUENCE16 &&
798 ber->be_encoding != BER_TYPE_SET17)
799 goto fail;
800 if (ber->be_subbe_union.bv_sub == NULL((void *)0) || level >= _MAX_SEQ128-1)
801 goto fail;
802 parent[++level] = ber;
803 ber = ber->be_subbe_union.bv_sub;
804 ret++;
805 continue;
806 case '}':
807 case ')':
808 if (level < 0 || parent[level] == NULL((void *)0))
809 goto fail;
810 ber = parent[level--];
811 ret++;
812 break;
813 default:
814 goto fail;
815 }
816
817 ber = ber->be_next;
818 }
819 va_end(ap)__builtin_va_end(ap);
820 return (ret == n ? 0 : -1);
821
822 fail:
823 va_end(ap)__builtin_va_end(ap);
824 return (-1);
825
826}
827
828ssize_t
829ober_get_writebuf(struct ber *b, void **buf)
830{
831 if (b->br_wbuf == NULL((void *)0))
832 return -1;
833 *buf = b->br_wbuf;
834 return (b->br_wend - b->br_wbuf);
835}
836
837/*
838 * write ber elements to the write buffer
839 *
840 * params:
841 * ber holds the destination write buffer byte stream
842 * root fully populated element tree
843 *
844 * returns:
845 * >=0 number of bytes written
846 * -1 on failure and sets errno
847 */
848ssize_t
849ober_write_elements(struct ber *ber, struct ber_element *root)
850{
851 size_t len;
852
853 /* calculate length because only the definite form is required */
854 len = ober_calc_len(root);
855 DPRINTF("write ber element of %zd bytes length\n", len)do { } while (0);
856
857 if (ber->br_wbuf != NULL((void *)0) && ber->br_wbuf + len > ber->br_wend) {
858 free(ber->br_wbuf);
859 ber->br_wbuf = NULL((void *)0);
860 }
861 if (ber->br_wbuf == NULL((void *)0)) {
862 if ((ber->br_wbuf = malloc(len)) == NULL((void *)0))
863 return -1;
864 ber->br_wend = ber->br_wbuf + len;
865 }
866
867 /* reset write pointer */
868 ber->br_wptr = ber->br_wbuf;
869
870 if (ober_dump_element(ber, root) == -1)
871 return -1;
872
873 return (len);
874}
875
876void
877ober_set_readbuf(struct ber *b, void *buf, size_t len)
878{
879 b->br_rbuf = b->br_rptr = buf;
880 b->br_rend = (u_int8_t *)buf + len;
881}
882
883/*
884 * read ber elements from the read buffer
885 *
886 * params:
887 * ber holds a fully populated read buffer byte stream
888 * root if NULL, build up an element tree from what we receive on
889 * the wire. If not null, use the specified encoding for the
890 * elements received.
891 *
892 * returns:
893 * !=NULL, elements read and store in the ber_element tree
894 * NULL, type mismatch or read error
895 */
896struct ber_element *
897ober_read_elements(struct ber *ber, struct ber_element *elm)
898{
899 struct ber_element *root = elm;
900
901 if (root == NULL((void *)0)) {
902 if ((root = ober_get_element(0)) == NULL((void *)0))
903 return NULL((void *)0);
904 }
905
906 DPRINTF("read ber elements, root %p\n", root)do { } while (0);
907
908 if (ober_read_element(ber, root) == -1) {
909 /* Cleanup if root was allocated by us */
910 if (elm == NULL((void *)0))
911 ober_free_elements(root);
912 return NULL((void *)0);
913 }
914
915 return root;
916}
917
918off_t
919ober_getpos(struct ber_element *elm)
920{
921 return elm->be_offs;
922}
923
924struct ber_element *
925ober_dup(struct ber_element *orig)
926{
927 struct ber_element *new;
928
929 if ((new = malloc(sizeof(*new))) == NULL((void *)0))
930 return NULL((void *)0);
931 memcpy(new, orig, sizeof(*new));
932 new->be_next = NULL((void *)0);
933 new->be_subbe_union.bv_sub = NULL((void *)0);
934
935 if (orig->be_next != NULL((void *)0)) {
936 if ((new->be_next = ober_dup(orig->be_next)) == NULL((void *)0))
937 goto fail;
938 }
939 if (orig->be_encoding == BER_TYPE_SEQUENCE16 ||
940 orig->be_encoding == BER_TYPE_SET17) {
941 if (orig->be_subbe_union.bv_sub != NULL((void *)0)) {
942 if ((new->be_subbe_union.bv_sub = ober_dup(orig->be_subbe_union.bv_sub)) == NULL((void *)0))
943 goto fail;
944 }
945 } else if (orig->be_encoding == BER_TYPE_OCTETSTRING4 ||
946 orig->be_encoding == BER_TYPE_BITSTRING3 ||
947 orig->be_encoding == BER_TYPE_OBJECT6) {
948 if (orig->be_valbe_union.bv_val != NULL((void *)0)) {
949 if ((new->be_valbe_union.bv_val = malloc(orig->be_len)) == NULL((void *)0))
950 goto fail;
951 memcpy(new->be_valbe_union.bv_val, orig->be_valbe_union.bv_val, orig->be_len);
952 }
953 } else
954 new->be_numericbe_union.bv_numeric = orig->be_numericbe_union.bv_numeric;
955 return new;
956 fail:
957 ober_free_elements(new);
958 return NULL((void *)0);
959}
960
961void
962ober_free_element(struct ber_element *root)
963{
964 if (root->be_subbe_union.bv_sub && (root->be_encoding == BER_TYPE_SEQUENCE16 ||
965 root->be_encoding == BER_TYPE_SET17))
966 ober_free_elements(root->be_subbe_union.bv_sub);
967 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING4 ||
968 root->be_encoding == BER_TYPE_BITSTRING3 ||
969 root->be_encoding == BER_TYPE_OBJECT6))
970 free(root->be_valbe_union.bv_val);
971 free(root);
972}
973
974void
975ober_free_elements(struct ber_element *root)
976{
977 if (root == NULL((void *)0))
978 return;
979 if (root->be_subbe_union.bv_sub && (root->be_encoding == BER_TYPE_SEQUENCE16 ||
980 root->be_encoding == BER_TYPE_SET17))
981 ober_free_elements(root->be_subbe_union.bv_sub);
982 if (root->be_next)
983 ober_free_elements(root->be_next);
984 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING4 ||
985 root->be_encoding == BER_TYPE_BITSTRING3 ||
986 root->be_encoding == BER_TYPE_OBJECT6))
987 free(root->be_valbe_union.bv_val);
988 free(root);
989}
990
991size_t
992ober_calc_len(struct ber_element *root)
993{
994 unsigned int t;
995 size_t s;
996 size_t size = 2; /* minimum 1 byte head and 1 byte size */
997
998 /* calculate the real length of a sequence or set */
999 if (root->be_subbe_union.bv_sub && (root->be_encoding == BER_TYPE_SEQUENCE16 ||
1000 root->be_encoding == BER_TYPE_SET17))
1001 root->be_len = ober_calc_len(root->be_subbe_union.bv_sub);
1002
1003 /* fix header length for extended types */
1004 if (root->be_type > BER_TYPE_SINGLE_MAX30)
1005 for (t = root->be_type; t > 0; t >>= 7)
1006 size++;
1007 if (root->be_len >= BER_TAG_MORE0x80)
1008 for (s = root->be_len; s > 0; s >>= 8)
1009 size++;
1010
1011 /* calculate the length of the following elements */
1012 if (root->be_next)
1013 size += ober_calc_len(root->be_next);
1014
1015 /* This is an empty element, do not use a minimal size */
1016 if (root->be_class == BER_CLASS_UNIVERSAL0x0 &&
1017 root->be_type == BER_TYPE_EOC0 && root->be_len == 0)
1018 return (0);
1019
1020 return (root->be_len + size);
1021}
1022
1023void
1024ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
1025{
1026 b->br_application = cb;
1027}
1028
1029void
1030ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
1031 void *arg)
1032{
1033 elm->be_cb = cb;
1034 elm->be_cbarg = arg;
1035}
1036
1037void
1038ober_free(struct ber *b)
1039{
1040 free(b->br_wbuf);
1041}
1042
1043/*
1044 * internal functions
1045 */
1046
1047static int
1048ober_dump_element(struct ber *ber, struct ber_element *root)
1049{
1050 unsigned long long l;
1051 int i;
1052 uint8_t u;
1053
1054 ober_dump_header(ber, root);
1055 if (root->be_cb)
1056 root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1057
1058 switch (root->be_encoding) {
1059 case BER_TYPE_BOOLEAN1:
1060 case BER_TYPE_INTEGER2:
1061 case BER_TYPE_ENUMERATED10:
1062 l = (unsigned long long)root->be_numericbe_union.bv_numeric;
1063 for (i = root->be_len; i > 0; i--) {
1064 u = (l >> ((i - 1) * 8)) & 0xff;
1065 ober_putc(ber, u);
1066 }
1067 break;
1068 case BER_TYPE_BITSTRING3:
1069 case BER_TYPE_OCTETSTRING4:
1070 case BER_TYPE_OBJECT6:
1071 ober_write(ber, root->be_valbe_union.bv_val, root->be_len);
1072 break;
1073 case BER_TYPE_NULL5: /* no payload */
1074 case BER_TYPE_EOC0:
1075 break;
1076 case BER_TYPE_SEQUENCE16:
1077 case BER_TYPE_SET17:
1078 if (root->be_subbe_union.bv_sub && ober_dump_element(ber, root->be_subbe_union.bv_sub) == -1)
1079 return -1;
1080 break;
1081 }
1082
1083 if (root->be_next == NULL((void *)0))
1084 return 0;
1085 return ober_dump_element(ber, root->be_next);
1086}
1087
1088static void
1089ober_dump_header(struct ber *ber, struct ber_element *root)
1090{
1091 u_char id = 0, t, buf[5];
1092 unsigned int type;
1093 size_t size;
1094
1095 /* class universal, type encoding depending on type value */
1096 /* length encoding */
1097 if (root->be_type <= BER_TYPE_SINGLE_MAX30) {
1098 id = root->be_type | (root->be_class << BER_CLASS_SHIFT6);
1099 if (root->be_encoding == BER_TYPE_SEQUENCE16 ||
1100 root->be_encoding == BER_TYPE_SET17)
1101 id |= BER_TYPE_CONSTRUCTED0x20;
1102
1103 ober_putc(ber, id);
1104 } else {
1105 id = BER_TAG_MASK0x1f | (root->be_class << BER_CLASS_SHIFT6);
1106 if (root->be_encoding == BER_TYPE_SEQUENCE16 ||
1107 root->be_encoding == BER_TYPE_SET17)
1108 id |= BER_TYPE_CONSTRUCTED0x20;
1109
1110 ober_putc(ber, id);
1111
1112 for (t = 0, type = root->be_type; type > 0; type >>= 7)
1113 buf[t++] = type & ~BER_TAG_MORE0x80;
1114
1115 while (t-- > 0) {
1116 if (t > 0)
1117 buf[t] |= BER_TAG_MORE0x80;
1118 ober_putc(ber, buf[t]);
1119 }
1120 }
1121
1122 if (root->be_len < BER_TAG_MORE0x80) {
1123 /* short form */
1124 ober_putc(ber, root->be_len);
1125 } else {
1126 for (t = 0, size = root->be_len; size > 0; size >>= 8)
1127 buf[t++] = size & 0xff;
1128
1129 ober_putc(ber, t | BER_TAG_MORE0x80);
1130
1131 while (t > 0)
1132 ober_putc(ber, buf[--t]);
1133 }
1134}
1135
1136static void
1137ober_putc(struct ber *ber, u_char c)
1138{
1139 if (ber->br_wptr + 1 <= ber->br_wend)
1140 *ber->br_wptr = c;
1141 ber->br_wptr++;
1142}
1143
1144static void
1145ober_write(struct ber *ber, void *buf, size_t len)
1146{
1147 if (ber->br_wptr + len <= ber->br_wend)
1148 bcopy(buf, ber->br_wptr, len);
1149 ber->br_wptr += len;
1150}
1151
1152/*
1153 * extract a BER encoded tag. There are two types, a short and long form.
1154 */
1155static ssize_t
1156get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1157{
1158 u_char u;
1159 size_t i = 0;
1160 unsigned int t = 0;
1161
1162 if (ober_getc(b, &u) == -1)
1163 return -1;
1164
1165 *class = (u >> BER_CLASS_SHIFT6) & BER_CLASS_MASK0x3;
1166 *cstruct = (u & BER_TYPE_CONSTRUCTED0x20) == BER_TYPE_CONSTRUCTED0x20;
1167
1168 if ((u & BER_TAG_MASK0x1f) != BER_TAG_MASK0x1f) {
1169 *tag = u & BER_TAG_MASK0x1f;
1170 return 1;
1171 }
1172
1173 do {
1174 if (ober_getc(b, &u) == -1)
1175 return -1;
1176
1177 /* enforce minimal number of octets for tag > 30 */
1178 if (i == 0 && (u & ~BER_TAG_MORE0x80) == 0) {
1179 errno(*__errno()) = EINVAL22;
1180 return -1;
1181 }
1182
1183 t = (t << 7) | (u & ~BER_TAG_MORE0x80);
1184 i++;
1185 if (i > sizeof(unsigned int)) {
1186 errno(*__errno()) = ERANGE34;
1187 return -1;
1188 }
1189 } while (u & BER_TAG_MORE0x80);
1190
1191 *tag = t;
1192 return i + 1;
1193}
1194
1195/*
1196 * extract length of a ber object -- if length is unknown an error is returned.
1197 */
1198static ssize_t
1199get_len(struct ber *b, ssize_t *len)
1200{
1201 u_char u, n;
1202 ssize_t s, r;
1203
1204 if (ober_getc(b, &u) == -1)
1205 return -1;
1206 if ((u & BER_TAG_MORE0x80) == 0) {
1207 /* short form */
1208 *len = u;
1209 return 1;
1210 }
1211
1212 if (u == 0x80) {
1213 /* Indefinite length not supported. */
1214 errno(*__errno()) = EINVAL22;
1215 return -1;
1216 }
1217
1218 if (u == 0xff) {
1219 /* Reserved for future use. */
1220 errno(*__errno()) = EINVAL22;
1221 return -1;
1222 }
1223
1224 n = u & ~BER_TAG_MORE0x80;
1225 /*
1226 * Limit to a decent size that works on all of our architectures.
1227 */
1228 if (sizeof(int32_t) < n) {
1229 errno(*__errno()) = ERANGE34;
1230 return -1;
1231 }
1232 r = n + 1;
1233
1234 for (s = 0; n > 0; n--) {
1235 if (ober_getc(b, &u) == -1)
1236 return -1;
1237 s = (s << 8) | u;
1238 }
1239
1240 if (s < 0) {
1241 /* overflow */
1242 errno(*__errno()) = ERANGE34;
1243 return -1;
1244 }
1245
1246 *len = s;
1247 return r;
1248}
1249
1250static ssize_t
1251ober_read_element(struct ber *ber, struct ber_element *elm)
1252{
1253 long long val = 0;
1254 struct ber_element *next;
1255 unsigned int type;
1256 int i, class, cstruct, elements = 0;
1257 ssize_t len, r, totlen = 0;
1258 u_char c, last = 0;
1259
1260 if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1261 return -1;
1262 DPRINTF("ber read got class %d type %u, %s\n",do { } while (0)
1263 class, type, cstruct ? "constructed" : "primitive")do { } while (0);
1264 totlen += r;
1265 if ((r = get_len(ber, &len)) == -1)
1266 return -1;
1267 DPRINTF("ber read element size %zd\n", len)do { } while (0);
1268 totlen += r + len;
1269
1270 /* The encoding of boolean, integer, enumerated, and null values
1271 * must be primitive. */
1272 if (class == BER_CLASS_UNIVERSAL0x0)
1273 if (type == BER_TYPE_BOOLEAN1 ||
1274 type == BER_TYPE_INTEGER2 ||
1275 type == BER_TYPE_ENUMERATED10 ||
1276 type == BER_TYPE_NULL5)
1277 if (cstruct) {
1278 errno(*__errno()) = EINVAL22;
1279 return -1;
1280 }
1281
1282 /* If the total size of the element is larger than the buffer
1283 * don't bother to continue. */
1284 if (len > ber->br_rend - ber->br_rptr) {
1285 errno(*__errno()) = ECANCELED88;
1286 return -1;
1287 }
1288
1289 elm->be_type = type;
1290 elm->be_len = len;
1291 elm->be_offs = ber->br_offs; /* element position within stream */
1292 elm->be_class = class;
1293
1294 if (elm->be_encoding == 0) {
1295 /* try to figure out the encoding via class, type and cstruct */
1296 if (cstruct)
1297 elm->be_encoding = BER_TYPE_SEQUENCE16;
1298 else if (class == BER_CLASS_UNIVERSAL0x0)
1299 elm->be_encoding = type;
1300 else if (ber->br_application != NULL((void *)0)) {
1301 /*
1302 * Ask the application to map the encoding to a
1303 * universal type. For example, a SMI IpAddress
1304 * type is defined as 4 byte OCTET STRING.
1305 */
1306 elm->be_encoding = (*ber->br_application)(elm);
1307 } else
1308 /* last resort option */
1309 elm->be_encoding = BER_TYPE_NULL5;
1310 }
1311
1312 switch (elm->be_encoding) {
1313 case BER_TYPE_EOC0: /* End-Of-Content */
1314 break;
1315 case BER_TYPE_BOOLEAN1:
1316 if (len != 1) {
1317 errno(*__errno()) = EINVAL22;
1318 return -1;
1319 }
1320 case BER_TYPE_INTEGER2:
1321 case BER_TYPE_ENUMERATED10:
1322 if (len < 1) {
1323 errno(*__errno()) = EINVAL22;
1324 return -1;
1325 }
1326 if (len > (ssize_t)sizeof(long long)) {
1327 errno(*__errno()) = ERANGE34;
1328 return -1;
1329 }
1330 for (i = 0; i < len; i++) {
1331 if (ober_getc(ber, &c) != 1)
1332 return -1;
1333
1334 /* smallest number of contents octets only */
1335 if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1336 (i == 1 && last == 0xff && (c & 0x80) != 0)) {
1337 errno(*__errno()) = EINVAL22;
1338 return -1;
1339 }
1340
1341 val <<= 8;
1342 val |= c;
1343 last = c;
1344 }
1345
1346 /* sign extend if MSB is set */
1347 if (len < (ssize_t)sizeof(long long) &&
1348 (val >> ((len - 1) * 8) & 0x80))
1349 val |= ULLONG_MAX(9223372036854775807LL*2ULL+1ULL) << (len * 8);
1350 elm->be_numericbe_union.bv_numeric = val;
1351 break;
1352 case BER_TYPE_BITSTRING3:
1353 elm->be_valbe_union.bv_val = malloc(len);
1354 if (elm->be_valbe_union.bv_val == NULL((void *)0))
1355 return -1;
1356 elm->be_free = 1;
1357 elm->be_len = len;
1358 ober_read(ber, elm->be_valbe_union.bv_val, len);
1359 break;
1360 case BER_TYPE_OCTETSTRING4:
1361 case BER_TYPE_OBJECT6:
1362 elm->be_valbe_union.bv_val = malloc(len + 1);
1363 if (elm->be_valbe_union.bv_val == NULL((void *)0))
1364 return -1;
1365 elm->be_free = 1;
1366 elm->be_len = len;
1367 ober_read(ber, elm->be_valbe_union.bv_val, len);
1368 ((u_char *)elm->be_valbe_union.bv_val)[len] = '\0';
1369 break;
1370 case BER_TYPE_NULL5: /* no payload */
1371 if (len != 0) {
1372 errno(*__errno()) = EINVAL22;
1373 return -1;
1374 }
1375 break;
1376 case BER_TYPE_SEQUENCE16:
1377 case BER_TYPE_SET17:
1378 if (elm->be_subbe_union.bv_sub == NULL((void *)0)) {
1379 if ((elm->be_subbe_union.bv_sub = ober_get_element(0)) == NULL((void *)0))
1380 return -1;
1381 }
1382 next = elm->be_subbe_union.bv_sub;
1383 while (len > 0) {
1384 /*
1385 * Prevent stack overflow from excessive recursion
1386 * depth in ober_free_elements().
1387 */
1388 if (elements >= BER_MAX_SEQ_ELEMENTS(32767 *2 +1)) {
1389 errno(*__errno()) = ERANGE34;
1390 return -1;
1391 }
1392 r = ober_read_element(ber, next);
1393 if (r == -1)
1394 return -1;
1395 elements++;
1396 len -= r;
1397 if (len > 0 && next->be_next == NULL((void *)0)) {
1398 if ((next->be_next = ober_get_element(0)) ==
1399 NULL((void *)0))
1400 return -1;
1401 }
1402 next = next->be_next;
1403 }
1404 break;
1405 }
1406 return totlen;
1407}
1408
1409static ssize_t
1410ober_getc(struct ber *b, u_char *c)
1411{
1412 return ober_read(b, c, 1);
1413}
1414
1415static ssize_t
1416ober_read(struct ber *ber, void *buf, size_t len)
1417{
1418 size_t sz;
1419
1420 if (ber->br_rbuf == NULL((void *)0)) {
1421 errno(*__errno()) = ENOBUFS55;
1422 return -1;
1423 }
1424
1425 sz = ber->br_rend - ber->br_rptr;
1426 if (len > sz) {
1427 errno(*__errno()) = ECANCELED88;
1428 return -1; /* parser wants more data than available */
1429 }
1430
1431 bcopy(ber->br_rptr, buf, len);
1432 ber->br_rptr += len;
1433 ber->br_offs += len;
1434
1435 return len;
1436}