]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
opencdk: read_attribute: added more precise checks when reading stream
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 4 Jan 2017 13:42:03 +0000 (14:42 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 4 Jan 2017 14:24:57 +0000 (15:24 +0100)
That addresses heap read overflows found using oss-fuzz:
  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=338
  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=346

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/opencdk/read-packet.c

index cdb47007a6183a85bcd0ba9717cee67ffbb2dbba..b999e1c000bcdf5d674d10c6c1c00725db255a27 100644 (file)
@@ -482,46 +482,64 @@ read_attribute(cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr,
                return CDK_Out_Of_Core;
        rc = stream_read(inp, buf, pktlen, &nread);
        if (rc) {
-               cdk_free(buf);
-               return CDK_Inv_Packet;
+               gnutls_assert();
+               rc = CDK_Inv_Packet;
+               goto error;
        }
+
        p = buf;
        len = *p++;
        pktlen--;
+
        if (len == 255) {
+               if (pktlen < 4) {
+                       gnutls_assert();
+                       rc = CDK_Inv_Packet;
+                       goto error;
+               }
+
                len = _cdk_buftou32(p);
                p += 4;
                pktlen -= 4;
        } else if (len >= 192) {
                if (pktlen < 2) {
-                       cdk_free(buf);
-                       return CDK_Inv_Packet;
+                       gnutls_assert();
+                       rc = CDK_Inv_Packet;
+                       goto error;
                }
+
                len = ((len - 192) << 8) + *p + 192;
                p++;
                pktlen--;
        }
 
-       if (*p != 1) {          /* Currently only 1, meaning an image, is defined. */
-               cdk_free(buf);
-               return CDK_Inv_Packet;
+       if (!len || *p != 1) {          /* Currently only 1, meaning an image, is defined. */
+               rc = CDK_Inv_Packet;
+               goto error;
        }
+
        p++;
        len--;
 
        if (len >= pktlen) {
-               cdk_free(buf);
-               return CDK_Inv_Packet;
+               rc = CDK_Inv_Packet;
+               goto error;
        }
+
        attr->attrib_img = cdk_calloc(1, len);
        if (!attr->attrib_img) {
-               cdk_free(buf);
-               return CDK_Out_Of_Core;
+               rc = CDK_Out_Of_Core;
+               goto error;
        }
+
        attr->attrib_len = len;
        memcpy(attr->attrib_img, p, len);
        cdk_free(buf);
        return rc;
+
+ error:
+       cdk_free(buf);
+       return rc;
 }