From 32b62cf785e6d89a6ad525dff631da8a8924cecf Mon Sep 17 00:00:00 2001 From: LoboQ1ng Date: Tue, 10 Mar 2026 17:04:43 +0000 Subject: [PATCH] Fix NULL pointer dereference in CAB parser during skip When parsing a malformed CAB file, the skip routine (cab_checksum_finish) blindly calculated the checksum on an uninitialized cfdata->memimage. This patch adds a NULL check before the checksum calculation and includes a standalone test case with a minimized malformed payload to prevent regressions. --- libarchive/archive_read_support_format_cab.c | 3 + libarchive/test/CMakeLists.txt | 1 + .../test_read_format_cab_skip_malformed.c | 41 ++++++++ ...test_read_format_cab_skip_malformed.cab.uu | 95 +++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 libarchive/test/test_read_format_cab_skip_malformed.c create mode 100644 libarchive/test/test_read_format_cab_skip_malformed.cab.uu diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index 63755ef9e..8b6e8370c 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -1173,6 +1173,9 @@ cab_checksum_finish(struct archive_read *a) l = 4; if (cab->cfheader.flags & RESERVE_PRESENT) l += cab->cfheader.cfdata; + if (cfdata->memimage == NULL) { + return (ARCHIVE_FAILED); + } cfdata->sum_calculated = cab_checksum_cfdata( cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); if (cfdata->sum_calculated != cfdata->sum) { diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 02521c2bc..6f51e3c5f 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -114,6 +114,7 @@ IF(ENABLE_TEST) test_read_format_ar.c test_read_format_cab.c test_read_format_cab_filename.c + test_read_format_cab_skip_malformed.c test_read_format_cpio_afio.c test_read_format_cpio_bin.c test_read_format_cpio_bin_Z.c diff --git a/libarchive/test/test_read_format_cab_skip_malformed.c b/libarchive/test/test_read_format_cab_skip_malformed.c new file mode 100644 index 000000000..05cc80b79 --- /dev/null +++ b/libarchive/test/test_read_format_cab_skip_malformed.c @@ -0,0 +1,41 @@ +#include "test.h" + +DEFINE_TEST(test_read_format_cab_skip_malformed) +{ + /* Reference to the malformed CAB file */ + const char *refname = "test_read_format_cab_skip_malformed.cab"; + struct archive *a; + struct archive_entry *ae; + void *buffer; + size_t buffersize; + + /* Extract the reference file into the test sandbox */ + extract_reference_file(refname); + + /* Read the entire file into memory */ + buffer = slurpfile(&buffersize, "%s", refname); + assert(buffer != NULL); + + /* Initialize the archive reader */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + /* Read from memory (a prerequisite for triggering this specific bug) */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buffer, buffersize)); + + /* Simulate the parsing flow to trigger the implicit skip routine */ + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + const void *buff; + size_t size_read; + int64_t offset; + while (archive_read_data_block(a, &buff, &size_read, &offset) == ARCHIVE_OK) { + /* Consume data. This will fail quickly due to the malformed payload. */ + } + } + + /* Clean up. If the patch is effective, the program reaches here safely. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buffer); +} \ No newline at end of file diff --git a/libarchive/test/test_read_format_cab_skip_malformed.cab.uu b/libarchive/test/test_read_format_cab_skip_malformed.cab.uu new file mode 100644 index 000000000..7ec834335 --- /dev/null +++ b/libarchive/test/test_read_format_cab_skip_malformed.cab.uu @@ -0,0 +1,95 @@ +begin 664 test_read_format_cab_skip_malformed.cab +M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$``-(!```! +M.]+2"0D)"0D)"0D)"0D)"0D)"0FRLK*R"0D)"0D)"0D)"0D)LK*RLK*RLK(` +M``````````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,``````````````` +M````LK*RX____[:RL@```````````````#`W,"]`````"G!P`````&UDL@HP +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````%!+`P0````!#`P,#`P,#`P,#`P,#```````````````__\```3_ +M``!(___H````````````````````````````````````````____________ +M____________________________________________________```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M@```````````````@`````$````````````````````````````````````` +M````````````````````````````````````````````#`H,#````'H,#`P` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````#__P``!/\``$C__^@```````````#_________________________ +M______________________________________\````````````````````` +M`"\O+R\O+R\O+R\O+R\O+R\O+R\O+R\G+PHQ-C4P+U):22\P-S!,4EI)"@HO +M=6YS970@