From ebdba490384924ef422b1df675ba11d5030faf09 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 30 May 2015 15:48:05 -0500 Subject: [PATCH] Disallow empty blobs from being read --- include/wimlib/blob_table.h | 15 ++++++++++++++- src/blob_table.c | 14 ++++++++++++-- src/extract.c | 4 ++++ src/inode.c | 10 +++++----- src/win32_capture.c | 3 +++ 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/include/wimlib/blob_table.h b/include/wimlib/blob_table.h index dcf6af7f..0ccccfbb 100644 --- a/include/wimlib/blob_table.h +++ b/include/wimlib/blob_table.h @@ -74,7 +74,20 @@ struct blob_descriptor { /* List node for a hash bucket of the blob table */ struct hlist_node hash_list; - /* Uncompressed size of this blob */ + /* + * Uncompressed size of this blob. + * + * In most cases we are now enforcing that this is nonzero; i.e. an + * empty stream will have "no blob" rather than "an empty blob". The + * exceptions are: + * + * - blob descriptors with 'blob_location == BLOB_NONEXISTENT', + * e.g. placeholder entries for new metadata resources or for + * blobs required for pipable WIM extraction. In these cases the + * size is not meaningful information anyway. + * - blob descriptors with 'blob_location == BLOB_IN_STAGING_FILE' + * can vary their size over time, including to 0. + */ u64 size; union { diff --git a/src/blob_table.c b/src/blob_table.c index 4ec6cd93..d2ece47b 100644 --- a/src/blob_table.c +++ b/src/blob_table.c @@ -856,6 +856,7 @@ read_blob_table(WIMStruct *wim) struct blob_table *table = NULL; struct blob_descriptor *cur_blob = NULL; size_t num_duplicate_blobs = 0; + size_t num_empty_blobs = 0; size_t num_wrong_part_blobs = 0; u32 image_index = 0; struct wim_resource_descriptor **cur_solid_rdescs = NULL; @@ -976,12 +977,18 @@ read_blob_table(WIMStruct *wim) /* cur_blob is now a blob bound to a resource. */ /* Ignore entries with all zeroes in the hash field. */ - if (is_zero_hash(cur_blob->hash)) + if (unlikely(is_zero_hash(cur_blob->hash))) goto free_cur_blob_and_continue; + /* Verify that the blob has nonzero size. */ + if (unlikely(cur_blob->size == 0)) { + num_empty_blobs++; + goto free_cur_blob_and_continue; + } + /* Verify that the part number matches that of the underlying * WIM file. */ - if (part_number != wim->hdr.part_number) { + if (unlikely(part_number != wim->hdr.part_number)) { num_wrong_part_blobs++; goto free_cur_blob_and_continue; } @@ -1084,6 +1091,9 @@ read_blob_table(WIMStruct *wim) if (num_duplicate_blobs > 0) WARNING("Ignoring %zu duplicate blobs", num_duplicate_blobs); + if (num_empty_blobs > 0) + WARNING("Ignoring %zu empty blobs", num_empty_blobs); + if (num_wrong_part_blobs > 0) { WARNING("Ignoring %zu blobs with wrong part number", num_wrong_part_blobs); diff --git a/src/extract.c b/src/extract.c index 99320268..83477f13 100644 --- a/src/extract.c +++ b/src/extract.c @@ -181,6 +181,10 @@ read_pwm_blob_header(WIMStruct *pwm, struct blob_descriptor *blob, wim_res_hdr_to_desc(&reshdr, pwm, rdesc); blob_set_is_located_in_nonsolid_wim_resource(blob, rdesc); blob->is_metadata = (rdesc->flags & WIM_RESHDR_FLAG_METADATA) != 0; + + if (unlikely(blob->size == 0)) + return WIMLIB_ERR_INVALID_PIPABLE_WIM; + return 0; read_error: diff --git a/src/inode.c b/src/inode.c index 16ae0d22..690eb22f 100644 --- a/src/inode.c +++ b/src/inode.c @@ -498,8 +498,8 @@ blob_not_found_error(const struct wim_inode *inode, const u8 *hash) } /* - * Return the blob descriptor for the specified stream, or NULL if the blob for - * the stream is empty or not available. + * Return the blob descriptor for the specified stream, or NULL if the stream is + * empty or its blob is not available in @table. */ struct blob_descriptor * stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table) @@ -523,9 +523,9 @@ stream_hash(const struct wim_inode_stream *strm) /* * Return the blob descriptor for the unnamed data stream of the inode, or NULL - * if the inode does not have an unnamed data stream, the blob for the inode's - * unnamed data stream is empty, or the blob for the inode's unnamed data stream - * is not available in @blob_table. + * if the inode does not have an unnamed data stream, the inode's unnamed data + * stream is empty, or the blob for the inode's unnamed data stream is not + * available in @blob_table. */ struct blob_descriptor * inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode, diff --git a/src/win32_capture.c b/src/win32_capture.c index 3061f6ae..ba9937cf 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -852,6 +852,9 @@ winnt_scan_efsrpc_raw_data(struct wim_inode *inode, const wchar_t *nt_path, if (ret) goto err; + /* Empty EFSRPC data does not make sense */ + wimlib_assert(blob->size != 0); + strm = inode_add_stream(inode, STREAM_TYPE_EFSRPC_RAW_DATA, NO_STREAM_NAME, blob); if (!strm) -- 2.43.0