Disallow empty blobs from being read
authorEric Biggers <ebiggers3@gmail.com>
Sat, 30 May 2015 20:48:05 +0000 (15:48 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 2 Jun 2015 02:57:47 +0000 (21:57 -0500)
include/wimlib/blob_table.h
src/blob_table.c
src/extract.c
src/inode.c
src/win32_capture.c

index dcf6af7..0ccccfb 100644 (file)
@@ -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 {
index 4ec6cd9..d2ece47 100644 (file)
@@ -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);
index 9932026..83477f1 100644 (file)
@@ -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:
index 16ae0d2..690eb22 100644 (file)
@@ -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,
index 3061f6a..ba9937c 100644 (file)
@@ -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)