CVE-2021-3881 (published 2021-10-15T14:15Z)

libmobi is vulnerable to Out-of-bounds Read

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/bfabiszewski/libmobi
commit_details: repo_url: https://github.com/bfabiszewski/libmobi
author: Bartek Fabiszewski
author_date: 2021-09-18 21:55:27+02:00
msg: Fix potential out-of-buffer read while parsing corrupt file, closes #35, #36
repository: repo_url: https://github.com/bfabiszewski/libmobi
repo_name: bfabiszewski/libmobi
description: C library for handling Kindle (MOBI) formats of ebook documents
repo_language: C
owner: bfabiszewski
file_changes: filename: compression.c
change_type: ModificationType.MODIFY
diff: @@ -141,7 +141,10 @@ static MOBI_RET mobi_decompress_huffman_internal(MOBIBuffer *buf_out, MOBIBuffer
         if (!(t1 & 0x80)) {
             /* get offset from mincode, maxcode tables */
             while (code < huffcdic->mincode_table[code_length]) {
-                code_length++;
+                if (++code_length >= HUFF_CODETABLE_SIZE) {
+                    debug_print("Wrong offset to mincode table: %hhu\n", code_length);
+                    return MOBI_DATA_CORRUPT;
+                }
             }
             maxcode = huffcdic->maxcode_table[code_length];
         }

programming_language: C
filename: compression.h
change_type: ModificationType.MODIFY
diff: @@ -20,6 +20,7 @@
 
 /* FIXME: what is the reasonable value? */
 #define MOBI_HUFFMAN_MAXDEPTH 20 /**< Maximal recursion level for huffman decompression routine */
+#define HUFF_CODETABLE_SIZE 33 /**< Size of min- and maxcode tables */
 
 
 /**
@@ -30,8 +31,8 @@ typedef struct {
     size_t index_read; /**< Number of indices parsed, used by parser */
     size_t code_length; /**< Code length value stored in CDIC record header */
     uint32_t table1[256]; /**< Table of big-endian indices from HUFF record data1 */
-    uint32_t mincode_table[33]; /**< Table of big-endian mincodes from HUFF record data2 */
-    uint32_t maxcode_table[33]; /**< Table of big-endian maxcodes from HUFF record data2 */
+    uint32_t mincode_table[HUFF_CODETABLE_SIZE]; /**< Table of big-endian mincodes from HUFF record data2 */
+    uint32_t maxcode_table[HUFF_CODETABLE_SIZE]; /**< Table of big-endian maxcodes from HUFF record data2 */
     uint16_t *symbol_offsets; /**< Index of symbol offsets parsed from CDIC records (index_count entries) */
     unsigned char **symbols; /**< Array of pointers to start of symbols data in each CDIC record (index = number of CDIC record) */
 } MOBIHuffCdic;

programming_language: C
filename: read.c
change_type: ModificationType.MODIFY
diff: @@ -589,7 +589,7 @@ MOBI_RET mobi_parse_huff(MOBIHuffCdic *huffcdic, const MOBIPdbRecord *record) {
     /* read 32 mincode-maxcode pairs from data2 big-endian */
     huffcdic->mincode_table[0] = 0;
     huffcdic->maxcode_table[0] = 0xFFFFFFFF;
-    for (int i = 1; i < 33; i++) {
+    for (int i = 1; i < HUFF_CODETABLE_SIZE; i++) {
         const uint32_t mincode = mobi_buffer_get32(buf);
         const uint32_t maxcode = mobi_buffer_get32(buf);
         huffcdic->mincode_table[i] =  mincode << (32 - i);

programming_language: C