/* Many systems define min or MIN, but not all. */
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
+/* True if this entry has declared a specific uncompressed size. */
+static int
+zip_entry_size_is_set(const struct zip_entry *zip_entry)
+{
+ return (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
+ || (zip_entry->uncompressed_size > 0
+ && zip_entry->uncompressed_size != 0xffffffff));
+}
+
#ifdef HAVE_ZLIB_H
static int
zip_read_data_deflate(struct archive_read *a, const void **buff,
"Read error skipping symlink target name");
return ARCHIVE_FATAL;
}
- } else if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
- || (zip_entry->uncompressed_size > 0
- && zip_entry->uncompressed_size != 0xffffffff)) {
- /* Set the size only if it's meaningful. */
+ } else if (zip_entry_size_is_set(zip_entry)) {
archive_entry_set_size(entry, zip_entry->uncompressed_size);
}
zip->entry_bytes_remaining = zip_entry->compressed_size;
}
if (r != ARCHIVE_OK)
return (r);
+
+ /*
+ * FAIL if there are more uncompressed bytes than were
+ * initially advertised. The end-of-entry check below also
+ * compares these values, but only once decoding reaches its
+ * own natural end. Fail the entry so a caller relying on
+ * archive_entry_size() as a hard boundary is never misled;
+ * later entries in the archive can still be read normally.
+ */
+ if (*size > 0 && zip_entry_size_is_set(zip->entry) &&
+ zip->entry_uncompressed_bytes_read > zip->entry->uncompressed_size) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "ZIP uncompressed data is larger than the declared "
+ "entry size (read at least %jd, expected %jd)",
+ (intmax_t)zip->entry_uncompressed_bytes_read,
+ (intmax_t)zip->entry->uncompressed_size);
+ return (ARCHIVE_FAILED);
+ }
+
if (*size > 0) {
zip->computed_crc32 = zip->crc32func(zip->computed_crc32, *buff,
(unsigned)*size);