From c6c9a2477ecf804e86befe4d4cae0b9088c0c813 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 21 May 2013 23:04:31 -0500 Subject: [PATCH 1/1] Correctly handle cyclic directory structures --- NEWS | 7 ++++++- src/dentry.c | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 71d306c5..5cc48a9c 100644 --- a/NEWS +++ b/NEWS @@ -43,7 +43,12 @@ Version 1.4.1: NTFS-3g capture now only warns about two conditions previously treated as errors. - Fixed a couple issues with using wimlib-imagex on UDF filesystems. + Fixed a couple issues with using wimlib-imagex on UDF filesystems on + Windows. + + wimlib now correctly detects and returns an error when reading a WIM + image with a cyclic directory structure. (Fun fact: such a WIM will + crash Microsoft's software.) Version 1.4.0: Added new "extract" and "update" subcommands to wimlib-imagex, along diff --git a/src/dentry.c b/src/dentry.c index c62a694f..50317193 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -1906,6 +1906,7 @@ read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, u64 cur_offset = dentry->subdir_offset; struct wim_dentry *child; struct wim_dentry *duplicate; + struct wim_dentry *parent; struct wim_dentry cur_child; int ret; @@ -1918,6 +1919,18 @@ read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, if (cur_offset == 0) return 0; + /* Check for cyclic directory structure */ + for (parent = dentry->parent; !dentry_is_root(parent); parent = parent->parent) + { + if (unlikely(parent->subdir_offset == cur_offset)) { + ERROR("Cyclic directory structure directed: children " + "of \"%"TS"\" coincide with children of \"%"TS"\"", + dentry_full_path(dentry), + dentry_full_path(parent)); + return WIMLIB_ERR_INVALID_DENTRY; + } + } + /* Find and read all the children of @dentry. */ for (;;) { @@ -1948,7 +1961,7 @@ read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, cur_offset += dentry_total_length(child); duplicate = dentry_add_child(dentry, child); - if (duplicate) { + if (unlikely(duplicate)) { const tchar *child_type, *duplicate_type; child_type = dentry_get_file_type_string(child); duplicate_type = dentry_get_file_type_string(duplicate); @@ -1962,7 +1975,7 @@ read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, /* If there are children of this child, call this * procedure recursively. */ if (child->subdir_offset != 0) { - if (dentry_is_directory(child)) { + if (likely(dentry_is_directory(child))) { ret = read_dentry_tree(metadata_resource, metadata_resource_len, child); -- 2.43.0