/* 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 {
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;
/* 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;
}
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);
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:
}
/*
- * 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)
/*
* 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,
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)