[gcab] Do not crash when ncbytes is larger than the buffer size



commit bd2abee5f0a9b5cbe3a1ab1f338c4fb8f6ca797b
Author: Richard Hughes <richard hughsie com>
Date:   Mon Dec 18 10:57:23 2017 +0000

    Do not crash when ncbytes is larger than the buffer size
    
    This fixes CVE-2018-5345

 libgcab/cabinet.c               |   28 ++++++++++++++++++++++++----
 tests/test-ncbytes-overflow.cab |  Bin 0 -> 95066 bytes
 2 files changed, 24 insertions(+), 4 deletions(-)
---
diff --git a/libgcab/cabinet.c b/libgcab/cabinet.c
index dbea962..82bf884 100644
--- a/libgcab/cabinet.c
+++ b/libgcab/cabinet.c
@@ -531,21 +531,41 @@ cdata_read (cdata_t *cd, guint8 res_data, gint comptype,
     gboolean success = FALSE;
     int ret, zret = Z_OK;
     gint compression = comptype & GCAB_COMPRESSION_MASK;
-    guint8 *buf = compression == GCAB_COMPRESSION_NONE ? cd->out : cd->in;
+    gsize buf_sz;
+    guint8 *buf = NULL;
     guint32 datacsum;
     guint32 checksum_tmp;
     guint8 sizecsum[4];
     guint16 nbytes_le;
 
-    if (compression > GCAB_COMPRESSION_MSZIP &&
-        compression != GCAB_COMPRESSION_LZX) {
+    /* decompress directly into ->out for no decompression */
+    switch (compression) {
+    case GCAB_COMPRESSION_NONE:
+        buf = cd->out;
+        buf_sz = sizeof(cd->out);
+        break;
+    case GCAB_COMPRESSION_MSZIP:
+    case GCAB_COMPRESSION_LZX:
+        buf = cd->in;
+        buf_sz = sizeof(cd->in);
+        break;
+    default:
         g_set_error (error, GCAB_ERROR, GCAB_ERROR_NOT_SUPPORTED,
                      "unsupported compression method %d", compression);
-        return FALSE;
+        break;
     }
+    if (buf == NULL)
+        return FALSE;
 
     R4 (cd->checksum);
     R2 (cd->ncbytes);
+    if (cd->ncbytes > buf_sz) {
+        g_set_error (error, GCAB_ERROR, GCAB_ERROR_INVALID_DATA,
+                     "tried to decompress %" G_GUINT16_FORMAT " bytes "
+                     "into buffer of size %" G_GSIZE_FORMAT,
+                     cd->ncbytes, buf_sz);
+        return FALSE;
+    }
     R2 (cd->nubytes);
     RN (cd->reserved, res_data);
     RN (buf, cd->ncbytes);
diff --git a/tests/test-ncbytes-overflow.cab b/tests/test-ncbytes-overflow.cab
new file mode 100644
index 0000000..7adddbc
Binary files /dev/null and b/tests/test-ncbytes-overflow.cab differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]