CVE-2021-3889 (published 2021-10-19T13:15Z)

libmobi is vulnerable to Use of Out-of-range Pointer Offset

Severity: MEDIUM
CVSS v2 base score: 5.8 (AV:N/AC:M/Au:N/C:P/I:N/A:P)
CVSS v3 base score: 8.1, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:H)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

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