From 40632feda6a4f5d674c1e0d0ee088fd00fbf89b5 Mon Sep 17 00:00:00 2001 From: martijn Date: Fri, 10 Nov 2023 12:12:02 +0000 Subject: [PATCH] Give ober_printf_elements() a ber_element array, similar to ober_scanf_elements(). This allows us to move down and back up multiple levels in with nested sequences and sets. While here, on failure, make sure we free (and unlink if needed) all elements we created. OK claudio@, tb@ --- lib/libutil/ber.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/libutil/ber.c b/lib/libutil/ber.c index cd3bcd0623a..c21f2d8daf8 100644 --- a/lib/libutil/ber.c +++ b/lib/libutil/ber.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ber.c,v 1.25 2023/08/22 12:50:27 gerhard Exp $ */ +/* $OpenBSD: ber.c,v 1.26 2023/11/10 12:12:02 martijn Exp $ */ /* * Copyright (c) 2007, 2012 Reyk Floeter @@ -576,20 +576,25 @@ ober_get_oid(struct ber_element *elm, struct ber_oid *o) return (0); } +#define _MAX_SEQ 128 struct ber_element * ober_printf_elements(struct ber_element *ber, char *fmt, ...) { va_list ap; - int d, class; + int d, class, level = 0; size_t len; unsigned int type; long long i; char *s; void *p; struct ber_oid *o; - struct ber_element *sub = ber, *e; + struct ber_element *parent[_MAX_SEQ], *e; + struct ber_element *origber = ber, *firstber = NULL; + + memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ); va_start(ap, fmt); + while (*fmt) { switch (*fmt++) { case 'B': @@ -653,16 +658,24 @@ ober_printf_elements(struct ber_element *ber, char *fmt, ...) goto fail; break; case '{': - if ((ber = sub = ober_add_sequence(ber)) == NULL) + if (level >= _MAX_SEQ-1) + goto fail; + if ((ber= ober_add_sequence(ber)) == NULL) goto fail; + parent[level++] = ber; break; case '(': - if ((ber = sub = ober_add_set(ber)) == NULL) + if (level >= _MAX_SEQ-1) + goto fail; + if ((ber = ober_add_set(ber)) == NULL) goto fail; + parent[level++] = ber; break; case '}': case ')': - ber = sub; + if (level <= 0 || parent[level - 1] == NULL) + goto fail; + ber = parent[--level]; break; case '.': if ((e = ober_add_eoc(ber)) == NULL) @@ -672,19 +685,22 @@ ober_printf_elements(struct ber_element *ber, char *fmt, ...) default: break; } + if (firstber == NULL) + firstber = ber; } va_end(ap); return (ber); fail: - ober_free_elements(ber); + if (origber != NULL) + ober_unlink_elements(origber); + ober_free_elements(firstber); return (NULL); } int ober_scanf_elements(struct ber_element *ber, char *fmt, ...) { -#define _MAX_SEQ 128 va_list ap; int *d, level = -1; unsigned int *t; -- 2.20.1