]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
inode: move 'i_extra_size' to 'i_extra' buffer
[wimlib] / src / dentry.c
index 8b00da14029815122dcb30d4076a676aaa48f21a..ff1a21420f0c2c068d422c1b9645368e96133675 100644 (file)
@@ -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)