cab->uncompressed_buffer + cab->xstrm.total_out;
cab->xstrm.avail_out =
cfdata->uncompressed_size - cab->xstrm.total_out;
+
+ if ((size_t)cfdata->uncompressed_size > cab->uncompressed_buffer_size) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid CFDATA uncompressed size");
+ *avail = ARCHIVE_FATAL;
+ return (NULL);
+ }
d = __archive_read_ahead(a, 1, &bytes_avail);
if (d == NULL) {
--- /dev/null
+#include "test.h"
+
+/*
+ * Regression test for Heap Out-of-Bounds Write in CAB LZX decoder.
+ * This ensures that a malformed CFDATA uncompressed size does not
+ * bypass physical buffer limits and cause memory corruption during skips.
+ */
+DEFINE_TEST(test_read_format_cab_lzx_oob)
+{
+ const char *refname = "test_read_format_cab_lzx_oob.cab";
+ struct archive *a;
+ struct archive_entry *ae;
+ const void *buff;
+ size_t size;
+ int64_t offset;
+
+ /* * The test framework will automatically find 'test_read_format_cab_lzx_oob.cab.uu',
+ * decode it, and place the binary '.cab' in the temporary test directory.
+ */
+ extract_reference_file(refname);
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_cab(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+
+ /* If it fails to open, there's a problem with the test setup/file */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
+
+ /* Read the header of the malformed entry */
+ if (ARCHIVE_OK == archive_read_next_header(a, &ae)) {
+ /* * We do NOT assert ARCHIVE_OK here. The file is intentionally malformed.
+ * The goal is to ensure the patched decoder catches the malicious size
+ * and returns an error (ARCHIVE_FATAL or ARCHIVE_WARN) instead of crashing.
+ */
+ if (archive_read_data_block(a, &buff, &size, &offset) == ARCHIVE_OK) {
+ archive_read_data_skip(a);
+ } else {
+ /* Even if the first block read fails, force a skip to test state handling */
+ archive_read_data_skip(a);
+ }
+
+ /* * Optional: We could assert that the error string contains our patch message,
+ * but simply surviving without a segfault/ASAN violation is the primary goal
+ * for fuzzing regression tests.
+ */
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
\ No newline at end of file
--- /dev/null
+begin 664 test_read_format_cab_lzx_oob.cab
+M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$```$`0Q`!
+M`3O2T@D)"0D)"0D)``````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,```
+M````````````````LK*2X____[:RL@``````````LK*R"C``````````````
+M`````+*RDN/___^VLK(```````````"R'YV)3``````````````0$!`0$!`0
+M$!`0$!D0$!`0$!`0$!`0$!`0$!`0$!#___\/$!`0`````````$`0$`!`,#<P
+M-S`R````,#82SWXO+R\`_P``````````````````````````````````````
+M``````#U\DH*-S`R````,#82SWXO+R\`_P``````````````````````````
+.````````````````````
+`
+end