]> wimlib.net Git - wimlib/blobdiff - src/test_support.c
wlfuzz: don't generate hard linked reparse points
[wimlib] / src / test_support.c
index f4bd9855b78a6bfa5e6ad8e718bb54fa6573857f..15c707773bc73b6e26e8e3a8e9beeeb14615bc4c 100644 (file)
@@ -251,14 +251,13 @@ generate_random_security_descriptor(void *_desc, struct generation_context *ctx)
 static int
 set_random_metadata(struct wim_inode *inode, struct generation_context *ctx)
 {
-       u32 v = rand32();
-       u32 attrib = (v & (FILE_ATTRIBUTE_READONLY |
-                          FILE_ATTRIBUTE_HIDDEN |
-                          FILE_ATTRIBUTE_SYSTEM |
-                          FILE_ATTRIBUTE_ARCHIVE |
-                          FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
-                          FILE_ATTRIBUTE_COMPRESSED |
-                          FILE_ATTRIBUTE_SPARSE_FILE));
+       u32 attrib = (rand32() & (FILE_ATTRIBUTE_READONLY |
+                                 FILE_ATTRIBUTE_HIDDEN |
+                                 FILE_ATTRIBUTE_SYSTEM |
+                                 FILE_ATTRIBUTE_ARCHIVE |
+                                 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
+                                 FILE_ATTRIBUTE_COMPRESSED |
+                                 FILE_ATTRIBUTE_SPARSE_FILE));
 
        /* File attributes  */
        inode->i_attributes |= attrib;
@@ -447,14 +446,13 @@ add_random_data_stream(struct wim_inode *inode, struct generation_context *ctx,
 }
 
 static int
-set_random_streams(struct wim_inode *inode, struct generation_context *ctx,
-                  bool reparse_ok)
+set_random_streams(struct wim_inode *inode, struct generation_context *ctx)
 {
        int ret;
        u32 r;
 
        /* Reparse point (sometimes)  */
-       if (reparse_ok && rand32() % 8 == 0) {
+       if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
                ret = set_random_reparse_point(inode, ctx);
                if (ret)
                        return ret;
@@ -541,6 +539,7 @@ generate_random_filename(utf16lechar name[], int max_len,
        }
        len = min(len, max_len);
 
+retry:
        /* Generate the characters in the name. */
        for (int i = 0; i < len; i++) {
                do {
@@ -551,6 +550,11 @@ generate_random_filename(utf16lechar name[], int max_len,
        /* Add a null terminator. */
        name[len] = cpu_to_le16('\0');
 
+       /* Don't generate . and .. */
+       if (name[0] == cpu_to_le16('.') &&
+           (len == 1 || (len == 2 && name[1] == cpu_to_le16('.'))))
+               goto retry;
+
        return len;
 }
 
@@ -633,29 +637,12 @@ is_name_valid_in_win32_namespace(const utf16lechar *name)
 {
        const utf16lechar *p;
 
-       static const utf16lechar forbidden_names[][5] = {
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('N'), },
-               { cpu_to_le16('P'), cpu_to_le16('R'), cpu_to_le16('N'), },
-               { cpu_to_le16('A'), cpu_to_le16('U'), cpu_to_le16('X'), },
-               { cpu_to_le16('N'), cpu_to_le16('U'), cpu_to_le16('L'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('1'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('2'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('3'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('4'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('5'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('6'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('7'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('8'), },
-               { cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'), cpu_to_le16('9'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('1'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('2'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('3'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('4'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('5'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('6'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('7'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('8'), },
-               { cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'), cpu_to_le16('9'), },
+       static const char * const reserved_names[] = {
+                "CON",  "PRN",  "AUX",  "NUL",
+                "COM1", "COM2", "COM3", "COM4", "COM5",
+                "COM6", "COM7", "COM8", "COM9",
+                "LPT1", "LPT2", "LPT3", "LPT4", "LPT5",
+                "LPT6", "LPT7", "LPT8", "LPT9",
        };
 
        /* The name must be nonempty. */
@@ -670,10 +657,21 @@ is_name_valid_in_win32_namespace(const utf16lechar *name)
        /* Note: a trailing dot or space is permitted, even though on Windows
         * such a file can only be accessed using a WinNT-style path. */
 
-       /* The name can't be one of the reserved names (case insensitively). */
-       for (size_t i = 0; i < ARRAY_LEN(forbidden_names); i++)
-               if (!cmp_utf16le_strings_z(forbidden_names[i], name, true))
-                       return false;
+       /* The name can't be one of the reserved names or be a reserved name
+        * with an extension.  Case insensitive. */
+       for (size_t i = 0; i < ARRAY_LEN(reserved_names); i++) {
+               for (size_t j = 0; ; j++) {
+                       u16 c1 = le16_to_cpu(name[j]);
+                       u16 c2 = reserved_names[i][j];
+                       if (c2 == '\0') {
+                               if (c1 == '\0' || c1 == '.')
+                                       return false;
+                               break;
+                       }
+                       if (upcase[c1] != upcase[c2])
+                               break;
+               }
+       }
 
        return true;
 }
@@ -762,23 +760,27 @@ generate_dentry_tree_recursive(struct wim_dentry *dir, u32 depth,
                /* Generate the next child dentry.  */
                struct wim_inode *inode;
                u64 ino;
-               bool is_directory;
+               bool is_directory = (rand32() % 16 <= 6);
+               bool is_reparse = (rand32() % 8 == 0);
                utf16lechar name[63 + 1]; /* for UNIX extraction: 63 * 4 <= 255 */
                int name_len;
                struct wim_dentry *duplicate;
 
-               /* Decide whether to create a directory or not.  If not a
-                * directory, also decide on the inode number (i.e. we may
-                * generate a "hard link" to an existing file).  */
-               is_directory = ((rand32() % 16) <= 6);
-               if (is_directory)
+               /*
+                * Select an inode number for the new file.  Sometimes choose an
+                * existing inode number (i.e. create a hard link).  However,
+                * wimlib intentionally doesn't honor directory hard links, and
+                * reparse points cannot be represented in the WIM file format
+                * at all; so don't create hard links for such files.
+                */
+               if (is_directory || is_reparse)
                        ino = 0;
                else
                        ino = select_inode_number(ctx);
 
                /* Create the dentry. */
                ret = inode_table_new_dentry(ctx->params->inode_table, NULL,
-                                            ino, 0, is_directory, &child);
+                                            ino, 0, ino == 0, &child);
                if (ret)
                        return ret;
 
@@ -809,19 +811,19 @@ generate_dentry_tree_recursive(struct wim_dentry *dir, u32 depth,
 
                if (is_directory)
                        inode->i_attributes |= FILE_ATTRIBUTE_DIRECTORY;
+               if (is_reparse)
+                       inode->i_attributes |= FILE_ATTRIBUTE_REPARSE_POINT;
 
-               ret = set_random_metadata(inode, ctx);
+               ret = set_random_streams(inode, ctx);
                if (ret)
                        return ret;
 
-               ret = set_random_streams(inode, ctx, true);
+               ret = set_random_metadata(inode, ctx);
                if (ret)
                        return ret;
 
                /* Recurse if it's a directory.  */
-               if (is_directory &&
-                   !(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT))
-               {
+               if (is_directory && !is_reparse) {
                        ret = generate_dentry_tree_recursive(child, depth + 1,
                                                             ctx);
                        if (ret)
@@ -856,10 +858,10 @@ generate_dentry_tree(struct wim_dentry **root_ret, const tchar *_ignored,
        ret = inode_table_new_dentry(params->inode_table, NULL, 0, 0, true, &root);
        if (!ret) {
                root->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
-               ret = set_random_metadata(root->d_inode, &ctx);
+               ret = set_random_streams(root->d_inode, &ctx);
        }
        if (!ret)
-               ret = set_random_streams(root->d_inode, &ctx, false);
+               ret = set_random_metadata(root->d_inode, &ctx);
        if (!ret)
                ret = generate_dentry_tree_recursive(root, 1, &ctx);
        if (!ret)