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) {

Reply via email to