I found 2 minor issues in the handling of sequences/sets in
ober_read_element():
1) An empty sequence/set (which is basically always) unconditionally
   creates an (uninitialised) sub-element. Add the same length check
   used to check the next element
2) For each sub-element r is only checked for -1, but not if it
   overflows the length of the sequence itself. This is not a big risk
   since each sub-element is length-checked against the buffer
   availability and simply returns an ECANCELED, which would be no
   worse memory-wise than sending an extremely large packet.

While here, only having the NULL of the comparison on the next line
annoyed me.

OK?

martijn@

Index: ber.c
===================================================================
RCS file: /cvs/src/lib/libutil/ber.c,v
retrieving revision 1.23
diff -u -p -r1.23 ber.c
--- ber.c       21 Oct 2021 08:17:33 -0000      1.23
+++ ber.c       2 Nov 2022 06:28:33 -0000
@@ -1375,7 +1375,7 @@ ober_read_element(struct ber *ber, struc
                break;
        case BER_TYPE_SEQUENCE:
        case BER_TYPE_SET:
-               if (elm->be_sub == NULL) {
+               if (len > 0 && elm->be_sub == NULL) {
                        if ((elm->be_sub = ober_get_element(0)) == NULL)
                                return -1;
                }
@@ -1390,13 +1390,21 @@ ober_read_element(struct ber *ber, struc
                                return -1;
                        }
                        r = ober_read_element(ber, next);
-                       if (r == -1)
+                       if (r == -1) {
+                               /* sub-element overflows sequence/set */
+                               if (errno == ECANCELED)
+                                       errno = EINVAL;
                                return -1;
+                       }
+                       if (r > len) {
+                               errno = EINVAL;
+                               return -1;
+                       }
                        elements++;
                        len -= r;
                        if (len > 0 && next->be_next == NULL) {
-                               if ((next->be_next = ober_get_element(0)) ==
-                                   NULL)
+                               next->be_next = ober_get_element(0);
+                               if (next->be_next == NULL)
                                        return -1;
                        }
                        next = next->be_next;

Reply via email to