X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fdentry.c;h=ff1a21420f0c2c068d422c1b9645368e96133675;hp=8b00da14029815122dcb30d4076a676aaa48f21a;hb=f9894b7e0e2a2a46fffdf7274d8671fb00f98089;hpb=9548e5c2d3b53ad31fabc9f0631de461b5f28a51;ds=sidebyside diff --git a/src/dentry.c b/src/dentry.c index 8b00da14..ff1a2142 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -358,7 +358,8 @@ dentry_out_total_length(const struct wim_dentry *dentry) dentry->d_short_name_nbytes); len = ALIGN(len, 8); - len += ALIGN(inode->i_extra_size, 8); + if (inode->i_extra) + len += ALIGN(inode->i_extra->size, 8); if (!(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)) { /* @@ -1187,10 +1188,12 @@ read_extra_data(const u8 *p, const u8 *end, struct wim_inode *inode) p++; if (unlikely(p < end)) { - inode->i_extra = memdup(p, end - p); + inode->i_extra = MALLOC(sizeof(struct wim_inode_extra) + + end - p); if (!inode->i_extra) return WIMLIB_ERR_NOMEM; - inode->i_extra_size = end - p; + inode->i_extra->size = end - p; + memcpy(inode->i_extra->data, p, end - p); } return 0; } @@ -1394,7 +1397,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len, u64 calculated_size; int ret; - BUILD_BUG_ON(sizeof(struct wim_dentry_on_disk) != WIM_DENTRY_DISK_SIZE); + STATIC_ASSERT(sizeof(struct wim_dentry_on_disk) == WIM_DENTRY_DISK_SIZE); /* Before reading the whole dentry, we need to read just the length. * This is because a dentry of length 8 (that is, just the length field) @@ -1547,21 +1550,14 @@ dentry_is_dot_or_dotdot(const struct wim_dentry *dentry) static int read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len, - struct wim_dentry * restrict dir) + struct wim_dentry * restrict dir, unsigned depth) { u64 cur_offset = dir->d_subdir_offset; - /* Check for cyclic directory structure, which would cause infinite - * recursion if not handled. */ - for (struct wim_dentry *d = dir->d_parent; - !dentry_is_root(d); d = d->d_parent) - { - if (unlikely(d->d_subdir_offset == cur_offset)) { - ERROR("Cyclic directory structure detected: children " - "of \"%"TS"\" coincide with children of \"%"TS"\"", - dentry_full_path(dir), dentry_full_path(d)); - return WIMLIB_ERR_INVALID_METADATA_RESOURCE; - } + /* Disallow extremely deep or cyclic directory structures */ + if (unlikely(depth >= 16384)) { + ERROR("Directory structure too deep!"); + return WIMLIB_ERR_INVALID_METADATA_RESOURCE; } for (;;) { @@ -1614,7 +1610,8 @@ read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len, if (likely(dentry_is_directory(child))) { ret = read_dentry_tree_recursive(buf, buf_len, - child); + child, + depth + 1); if (ret) return ret; } else { @@ -1675,7 +1672,7 @@ read_dentry_tree(const u8 *buf, size_t buf_len, } if (likely(root->d_subdir_offset != 0)) { - ret = read_dentry_tree_recursive(buf, buf_len, root); + ret = read_dentry_tree_recursive(buf, buf_len, root, 0); if (ret) goto err_free_dentry_tree; } @@ -1780,9 +1777,9 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p) while ((uintptr_t)p & 7) *p++ = 0; - if (inode->i_extra_size) { + if (inode->i_extra) { /* Extra tagged items --- not usually present. */ - p = mempcpy(p, inode->i_extra, inode->i_extra_size); + p = mempcpy(p, inode->i_extra->data, inode->i_extra->size); /* Align to 8-byte boundary */ while ((uintptr_t)p & 7)