Just reminded myself of this one.
The manpage says nothing about ober_read_elements setting errno upon
failure, yet it does in most cases. Furthermore, applications like
snmpd use errno in ober_read_elements to determine if a read is
incomplete (checking for ECANCELED), without initializing errno to
0.
The danger here is that since some stale errno might linger and a
return from ober_read_elements with NULL could test against an old
errno.
Diff below tries to remedy this.
OK?
martijn@
Index: ber.c
===================================================================
RCS file: /cvs/src/lib/libutil/ber.c,v
retrieving revision 1.15
diff -u -p -r1.15 ber.c
--- ber.c 24 Oct 2019 12:39:26 -0000 1.15
+++ ber.c 3 Sep 2020 15:58:23 -0000
@@ -1266,8 +1266,10 @@ ober_read_element(struct ber *ber, struc
/* smallest number of contents octets only */
if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
- (i == 1 && last == 0xff && (c & 0x80) != 0))
+ (i == 1 && last == 0xff && (c & 0x80) != 0)) {
+ errno = EINVAL;
return -1;
+ }
val <<= 8;
val |= c;
@@ -1299,8 +1301,10 @@ ober_read_element(struct ber *ber, struc
((u_char *)elm->be_val)[len] = '\0';
break;
case BER_TYPE_NULL: /* no payload */
- if (len != 0)
+ if (len != 0) {
+ errno = EINVAL;
return -1;
+ }
break;
case BER_TYPE_SEQUENCE:
case BER_TYPE_SET:
@@ -1346,8 +1350,10 @@ ober_read(struct ber *ber, void *buf, si
{
size_t sz;
- if (ber->br_rbuf == NULL)
+ if (ber->br_rbuf == NULL) {
+ errno = ENOBUFS;
return -1;
+ }
sz = ber->br_rend - ber->br_rptr;
if (len > sz) {