From: Eric Biggers Date: Fri, 24 Aug 2012 00:44:42 +0000 (-0500) Subject: Code to handle some weird siutations and bad WIMs X-Git-Tag: v1.0.0~94 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=cfc2cfc859a047e24d002aa149f73d45d4979d24 Code to handle some weird siutations and bad WIMs - read_lookup_table(): It is now an error if uncompressed resources have different compressed and uncompressed size. - read_lookup_table(): It is now an error if two lookup table entries have the same SHA1 message digest. - write_metadata_resource(): Append 20 random bytes to the end of the metadata resource to make the metadata resource unique even if we capture exactly the same image again. --- diff --git a/src/lookup_table.c b/src/lookup_table.c index 0c6a55fc..0546f958 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -197,7 +197,7 @@ int read_lookup_table(WIMStruct *w) while (num_entries--) { const u8 *p; - struct lookup_table_entry *cur_entry; + struct lookup_table_entry *cur_entry, *duplicate_entry; if (fread(buf, 1, sizeof(buf), w->fp) != sizeof(buf)) { if (feof(w->fp)) { @@ -221,7 +221,31 @@ int read_lookup_table(WIMStruct *w) p = get_u16(p, &cur_entry->part_number); p = get_u32(p, &cur_entry->refcnt); p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash); + + duplicate_entry = __lookup_resource(table, cur_entry->hash); + if (duplicate_entry) { + ERROR("The WIM lookup table contains two entries with the " + "same SHA1 message digest!"); + ERROR("The first entry is:"); + print_lookup_table_entry(duplicate_entry); + ERROR("The second entry is:"); + print_lookup_table_entry(cur_entry); + ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; + goto out; + } lookup_table_insert(table, cur_entry); + + if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) + && (cur_entry->resource_entry.size != + cur_entry->resource_entry.original_size)) + { + ERROR("Found uncompressed resource with original size " + "not the same as compressed size"); + ERROR("The lookup table entry for the resource is as follows:"); + print_lookup_table_entry(cur_entry); + ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; + goto out; + } } DEBUG("Done reading lookup table."); w->lookup_table = table; diff --git a/src/resource.c b/src/resource.c index 4f093622..2dde8d55 100644 --- a/src/resource.c +++ b/src/resource.c @@ -431,18 +431,9 @@ int read_wim_resource(const struct lookup_table_entry *lte, u8 buf[], wimlib_assert(lte->wim->fp); ctype = wim_resource_compression_type(lte); - /* XXX This check should be moved elsewhere */ - if (ctype == WIM_COMPRESSION_TYPE_NONE && - lte->resource_entry.original_size != - lte->resource_entry.size) { - ERROR("WIM resource at offset %"PRIu64", size %"PRIu64 - "has an original size of %"PRIu64", but is " - "uncompressed", - lte->resource_entry.offset, - lte->resource_entry.size, - lte->resource_entry.original_size); - return WIMLIB_ERR_INVALID_RESOURCE_SIZE; - } + wimlib_assert(ctype != WIM_COMPRESSION_TYPE_NONE || + (lte->resource_entry.original_size == + lte->resource_entry.size)); if (raw || ctype == WIM_COMPRESSION_TYPE_NONE) return read_uncompressed_resource(lte->wim->fp, @@ -1178,9 +1169,18 @@ int write_metadata_resource(WIMStruct *w) int ret; u64 subdir_offset; struct dentry *root; - struct lookup_table_entry *lte; + struct lookup_table_entry *lte, *duplicate_lte; u64 metadata_original_size; + /* + * We append 20 random bytes to the metadata resource so that we don't + * have identical metadata resources if we happen to append exactly the + * same image twice without any changes in timestamps. If this were to + * happen, it would cause confusion about the number and order of images + * in the WIM. + */ + const unsigned random_tail_len = 20; + DEBUG("Writing metadata resource for image %d", w->current_image); root = wim_root_dentry(w); @@ -1191,7 +1191,7 @@ int write_metadata_resource(WIMStruct *w) else subdir_offset = 8 + root->length + 8; calculate_subdir_offsets(root, &subdir_offset); - metadata_original_size = subdir_offset; + metadata_original_size = subdir_offset + random_tail_len; buf = MALLOC(metadata_original_size); if (!buf) { ERROR("Failed to allocate %"PRIu64" bytes for " @@ -1203,7 +1203,8 @@ int write_metadata_resource(WIMStruct *w) DEBUG("Writing dentry tree."); p = write_dentry_tree(root, p); - wimlib_assert(p - buf == metadata_original_size); + randomize_byte_array(p, random_tail_len); + wimlib_assert(p - buf + random_tail_len == metadata_original_size); lte = wim_metadata_lookup_table_entry(w); @@ -1212,11 +1213,12 @@ int write_metadata_resource(WIMStruct *w) wimlib_get_compression_type(w), <e->output_resource_entry, lte->hash); - lookup_table_unlink(w->lookup_table, lte); lookup_table_insert(w->lookup_table, lte); + wimlib_assert(lte->out_refcnt == 0); lte->out_refcnt++; lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA; +out: FREE(buf); return ret; } diff --git a/src/util.c b/src/util.c index e5b0d9e7..985d11b8 100644 --- a/src/util.c +++ b/src/util.c @@ -141,6 +141,8 @@ static const char *error_strings[] = { = "Tried to select an image that does not exist in the WIM", [WIMLIB_ERR_INVALID_INTEGRITY_TABLE] = "The WIM's integrity table is invalid", + [WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY] + = "An entry in the WIM's lookup table is invalid", [WIMLIB_ERR_INVALID_PARAM] = "An invalid parameter was given", [WIMLIB_ERR_INVALID_RESOURCE_HASH] diff --git a/src/wimlib.h b/src/wimlib.h index 73f5c32a..9aa8a05a 100644 --- a/src/wimlib.h +++ b/src/wimlib.h @@ -328,6 +328,7 @@ enum wimlib_error_code { WIMLIB_ERR_INVALID_HEADER_SIZE, WIMLIB_ERR_INVALID_IMAGE, WIMLIB_ERR_INVALID_INTEGRITY_TABLE, + WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY, WIMLIB_ERR_INVALID_PARAM, WIMLIB_ERR_INVALID_RESOURCE_HASH, WIMLIB_ERR_INVALID_RESOURCE_SIZE,