CVE-2023-29418 (published 2023-04-06T05:15Z)

An issue was discovered in libbzip3.a in bzip3 before 1.2.3. There is an xwrite out-of-bounds read.

CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/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/kspalaiologos/bzip3
commit_details: repo_url: https://github.com/kspalaiologos/bzip3
author: Kamila Szewczyk
author_date: 2023-03-19 14:25:04+01:00
msg: safety checks for decoding/testing when the buffer size and block size are inconsistent, tentative CRC32 version for BE systems (needs further verification on SPARC?)
repository: repo_url: https://github.com/kspalaiologos/bzip3
repo_name: kspalaiologos/bzip3
description: A better and stronger spiritual successor to BZip2.
repo_language: C
owner: kspalaiologos
file_changes: filename: libbz3.c
change_type: ModificationType.MODIFY
diff: @@ -61,8 +61,15 @@ static const u32 crc32Table[256] = {
 };
 
 static u32 crc32sum(u32 crc, u8 * RESTRICT buf, size_t size) {
-    while (size--) crc = crc32Table[(crc ^ *(buf++)) & 0xff] ^ (crc >> 8);
-    return crc;
+    // Test endianness. The code needs to be different for LE and BE systems.
+    u32 test = 1;
+    if (*(u8 *) &test) {
+        while (size--) crc = crc32Table[(crc ^ *(buf++)) & 0xff] ^ (crc >> 8);
+        return crc;
+    } else {
+        while (size--) crc = crc32Table[((crc >> 24) ^ *(buf++)) & 0xff] ^ (crc << 8);
+        return crc;
+    }
 }
 
 /* LZP code. These constants were manually tuned to give the best compression ratio while using relatively

programming_language: C
filename: main.c
change_type: ModificationType.MODIFY
diff: @@ -242,6 +242,10 @@ static int process(FILE * input_des, FILE * output_des, int mode, int block_size
                 new_size = read_neutral_s32(byteswap_buf);
                 xread_noeof(&byteswap_buf, 1, 4, input_des);
                 old_size = read_neutral_s32(byteswap_buf);
+                if(old_size > block_size + 31) {
+                    fprintf(stderr, "Failed to decode a block: Inconsistent headers.\n");
+                    return 1;
+                }
                 xread_noeof(buffer, 1, new_size, input_des);
                 bytes_read += 8 + new_size;
                 if (bz3_decode_block(state, buffer, new_size, old_size) == -1) {
@@ -259,6 +263,10 @@ static int process(FILE * input_des, FILE * output_des, int mode, int block_size
                 new_size = read_neutral_s32(byteswap_buf);
                 xread_noeof(&byteswap_buf, 1, 4, input_des);
                 old_size = read_neutral_s32(byteswap_buf);
+                if(old_size > block_size + 31) {
+                    fprintf(stderr, "Failed to decode a block: Inconsistent headers.\n");
+                    return 1;
+                }
                 xread_noeof(buffer, 1, new_size, input_des);
                 bytes_read += 8 + new_size;
                 if (bz3_decode_block(state, buffer, new_size, old_size) == -1) {
@@ -332,6 +340,10 @@ static int process(FILE * input_des, FILE * output_des, int mode, int block_size
                     sizes[i] = read_neutral_s32(byteswap_buf);
                     xread_noeof(&byteswap_buf, 1, 4, input_des);
                     old_sizes[i] = read_neutral_s32(byteswap_buf);
+                    if(old_sizes[i] > block_size + 31) {
+                        fprintf(stderr, "Failed to decode a block: Inconsistent headers.\n");
+                        return 1;
+                    }
                     xread_noeof(buffers[i], 1, sizes[i], input_des);
                     bytes_read += 8 + sizes[i];
                 }
@@ -356,6 +368,10 @@ static int process(FILE * input_des, FILE * output_des, int mode, int block_size
                     sizes[i] = read_neutral_s32(byteswap_buf);
                     xread_noeof(&byteswap_buf, 1, 4, input_des);
                     old_sizes[i] = read_neutral_s32(byteswap_buf);
+                    if(old_sizes[i] > block_size + 31) {
+                        fprintf(stderr, "Failed to decode a block: Inconsistent headers.\n");
+                        return 1;
+                    }
                     xread_noeof(buffers[i], 1, sizes[i], input_des);
                     bytes_read += 8 + sizes[i];
                 }
@@ -691,6 +707,9 @@ int main(int argc, char * argv[]) {
     output_des = mode != MODE_TEST ? open_output(output, force) : NULL;
     input_des = open_input(input);
 
+    if(output != f2)
+        free(output);
+
     int r = process(input_des, output_des, mode, block_size, workers, verbose, input);
 
     fclose(input_des);

programming_language: C