From ba8edbaf442ff0b30ca9ee1d16a4a646876ed94c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Jul 2021 23:03:50 -0700 Subject: [PATCH] Warn rather than abort if SHA-1 is same but size is different Assertions should only be used for bugs in wimlib, but this scenario can also happen if there is a SHA-1 collision, or if the SHA-1 hash provided by the filesystem for a WIM-backed file on Windows is wrong. --- include/wimlib/blob_table.h | 2 +- src/blob_table.c | 18 +++++++++++++++--- src/template.c | 3 ++- src/win32_capture.c | 3 ++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/wimlib/blob_table.h b/include/wimlib/blob_table.h index f15c6117..d16f5a24 100644 --- a/include/wimlib/blob_table.h +++ b/include/wimlib/blob_table.h @@ -412,7 +412,7 @@ new_blob_from_data_buffer(const void *buffer, size_t size, extern struct blob_descriptor * after_blob_hashed(struct blob_descriptor *blob, struct blob_descriptor **back_ptr, - struct blob_table *blob_table); + struct blob_table *blob_table, struct wim_inode *inode); extern int hash_unhashed_blob(struct blob_descriptor *blob, struct blob_table *blob_table, diff --git a/src/blob_table.c b/src/blob_table.c index 3fcde011..0554a7a9 100644 --- a/src/blob_table.c +++ b/src/blob_table.c @@ -36,6 +36,7 @@ #include "wimlib/assert.h" #include "wimlib/bitops.h" #include "wimlib/blob_table.h" +#include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/endianness.h" #include "wimlib/error.h" @@ -1259,7 +1260,7 @@ new_blob_from_data_buffer(const void *buffer, size_t size, struct blob_descriptor * after_blob_hashed(struct blob_descriptor *blob, struct blob_descriptor **back_ptr, - struct blob_table *blob_table) + struct blob_table *blob_table, struct wim_inode *inode) { struct blob_descriptor *duplicate_blob; @@ -1273,7 +1274,16 @@ after_blob_hashed(struct blob_descriptor *blob, * this blob to the duplicate and update the reference to this * blob (from a stream) to point to the duplicate. The caller * is responsible for freeing @blob if needed. */ - wimlib_assert(duplicate_blob->size == blob->size); + if (duplicate_blob->size != blob->size) { + tchar hash_str[SHA1_HASH_SIZE * 2 + 1]; + + sprint_hash(blob->hash, hash_str); + WARNING("SHA-1 collision at \"%"TS"\"\n" + " (hash=%"TS", size=%"PRIu64", other_size=%"PRIu64").\n" + " File will be corrupted!", + inode_any_full_path(inode), hash_str, + blob->size, duplicate_blob->size); + } duplicate_blob->refcnt += blob->refcnt; blob->refcnt = 0; *back_ptr = duplicate_blob; @@ -1307,15 +1317,17 @@ hash_unhashed_blob(struct blob_descriptor *blob, struct blob_table *blob_table, struct blob_descriptor **blob_ret) { struct blob_descriptor **back_ptr; + struct wim_inode *inode; int ret; back_ptr = retrieve_pointer_to_unhashed_blob(blob); + inode = blob->back_inode; ret = sha1_blob(blob); if (ret) return ret; - *blob_ret = after_blob_hashed(blob, back_ptr, blob_table); + *blob_ret = after_blob_hashed(blob, back_ptr, blob_table, inode); return 0; } diff --git a/src/template.c b/src/template.c index e5413e5f..1c018df7 100644 --- a/src/template.c +++ b/src/template.c @@ -114,7 +114,8 @@ inode_copy_checksums(struct wim_inode *inode, back_ptr = retrieve_pointer_to_unhashed_blob(blob); copy_hash(blob->hash, template_blob->hash); - if (after_blob_hashed(blob, back_ptr, blob_table) != blob) + if (after_blob_hashed(blob, back_ptr, blob_table, + inode) != blob) free_blob_descriptor(blob); } } diff --git a/src/win32_capture.c b/src/win32_capture.c index 0298cf00..8c9d726d 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -1604,7 +1604,8 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode, return 0; back_ptr = retrieve_pointer_to_unhashed_blob(blob); copy_hash(blob->hash, hash); - if (after_blob_hashed(blob, back_ptr, blob_table) != blob) + if (after_blob_hashed(blob, back_ptr, blob_table, + inode) != blob) free_blob_descriptor(blob); } -- 2.43.0