}
in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
+ if(in_bytes < 1) {
+ /* libbz2 doesn't complain when caller feeds avail_in == 0. It will
+ * actually return success in this case, which is undesirable. This is
+ * why we need to make this check manually. */
+
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated bzip2 file body");
+ return (ARCHIVE_FATAL);
+ }
/* Setup buffer boundaries. */
zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff;
extract_reference_file(refname);
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 100));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+
+ /* This file shouldn't be properly decompressed, because it's invalid.
+ * However, unpacker should return an error during unpacking. Without the
+ * proper fix, the unpacker was entering an unlimited loop. */
+ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 1));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid)
+{
+ const char *refname = "test_read_format_zip_bz2_hang.zip";
+ struct archive *a;
+ struct archive_entry *ae;
+ char buf[8];
+
+ extract_reference_file(refname);
+
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
--- /dev/null
+begin 644 test_read_format_zip_bz2_hang.zip
+M4$L#!)LP,#`,,#`P,#`P,#`P,#`P,#`P,#`$`!P`,#`P,#`P"0`P,#`P,#`P
+1,#!U>`L`8(0P,#`P,#`P,#``
+`
+end