ntdll: Remove more path trailing chars. (try 2)

Vincent Pelletier plr.vincent at gmail.com
Sun Apr 17 03:27:56 CDT 2011


Add tests via FindFirstFileA.
Fixes bug 22635.
---
 dlls/kernel32/tests/file.c |  132 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/ntdll/path.c          |    8 ++-
 2 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 4e8136a..6c88e07 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -2004,10 +2004,100 @@ static void test_FindFirstFileA(void)
 {
     HANDLE handle;
     WIN32_FIND_DATAA data;
-    int err;
+    int err, i, is_nt;
     char buffer[5] = "C:\\";
     char buffer2[100];
     char nonexistent[MAX_PATH];
+    static const struct
+    {
+        const char *path;
+        int expected_success;
+        int not_implemented; /* AKA todo_wine */
+        int broken_in_nt;
+    }
+    disallowed_chars_test_cases[] = {
+        /* Disallowed chars being ignored: */
+        {"test-dir/.", 1, 0, 0},
+        {"test-dir\\.", 1, 0, 0},
+        {"test-dir<.", 1, 0, 0},
+        {"test-dir< ", 1, 0, 0},
+        {"test-dir>.", 1, 0, 0},
+        {"test-dir> ", 1, 0, 0},
+        {"test-dir\".", 1, 0, 0},
+        {"test-dir\" ", 1, 0, 0},
+        {"test-dir/>", 1, 0, 0},
+        {"test-dir/<", 1, 0, 0},
+        {"test-dir/\"", 1, 0, 0},
+        {"test-dir<>", 1, 0, 0},
+        {"test-dir<<", 1, 0, 0},
+        {"test-dir<\"", 1, 0, 0},
+        {"test-dir>>", 1, 0, 0},
+        {"test-dir><", 1, 0, 0},
+        {"test-dir>\"", 1, 0, 0},
+        {"test-dir\">", 1, 0, 0},
+        {"test-dir\"<", 1, 0, 0},
+        {"test-dir\"\"", 1, 0, 0},
+        {"test-dir\\<", 1, 0, 0},
+        {"test-dir\\>", 1, 0, 0},
+        {"test-dir\\\"", 1, 0, 0},
+        /* But space prevents forward & back slashes from being stripped */
+        {"test-dir <", 0, 1, 0},
+        {"test-dir/ ", 0, 0, 0},
+        {"test-dir/ .", 0, 0, 0},
+        {"test-dir/. ", 0, 1, 0},
+        {"test-dir\\ ", 0, 0, 0},
+        {"test-dir\\ .", 0, 0, 0},
+        {"test-dir\\. ", 0, 1, 0},
+        {"test-dir/. ", 0, 1, 0},
+        {"test-dir\\. ", 0, 1, 0},
+        /* But forward & back slashes are not tolerated on a file */
+        {"test-file/>", 0, 1, 0},
+        {"test-file/<", 0, 1, 0},
+        {"test-file/\"", 0, 1, 0},
+        {"test-file<>", 1, 0, 0},
+        {"test-file<<", 1, 0, 0},
+        {"test-file<\"", 1, 0, 0},
+        {"test-file>>", 1, 0, 0},
+        {"test-file><", 1, 0, 0},
+        {"test-file>\"", 1, 0, 0},
+        {"test-file\">", 1, 0, 0},
+        {"test-file\"<", 1, 0, 0},
+        {"test-file\"\"", 1, 0, 0},
+        {"test-file\\<", 0, 1, 0},
+        {"test-file\\>", 0, 1, 0},
+        {"test-file\\\"", 0, 1, 0},
+        /* Even when many */
+        {"test-dir\"\"\"\"\"", 1, 0, 0},
+        {"test-dir<<<><><>\"\"\"\"<<<>", 1, 0, 0},
+        /* But only in the end of path */
+        {"test-/>dir", 0, 0, 0},
+        {"/>test-dir", 0, 0, 0},
+        {">test-dir", 0, 0, 0},
+        {">>test-dir", 0, 0, 0},
+        {">test->dir", 0, 0, 0},
+        {"><test->dir", 0, 0, 0},
+        {"<test->dir", 0, 0, 0},
+        {"<\"test->dir", 0, 0, 0},
+        /* Slash after ignored chars is not ignored: */
+        {"test-dir//", 0, 0, 1},
+        {"test-dir</", 0, 0, 1},
+        {"test-dir>/", 0, 0, 1},
+        {"test-dir\"/", 0, 0, 1},
+        {"test-dir\\", 0, 0, 0},
+        {"test-dir\\\\", 0, 0, 0},
+        {"test-dir\\/", 0, 0, 1},
+        {"test-dir/\\", 0, 0, 0},
+        /* Disalowed chars being preserved: */
+        {"test-dir/:", 0, 0, 0},
+        {"test-dir/|", 0, 0, 0},
+        /* Slashes converted to backslashes */
+        {"test-dir/", 0, 0, 1},
+        {"./test-dir", 1, 0, 0},
+        {"./test-dir/", 0, 0, 1},
+        {"test-dir\\", 0, 0, 0},
+        {".\\test-dir", 1, 0, 0},
+        {".\\test-dir\\", 0, 0, 0},
+    };
 
     /* try FindFirstFileA on "C:\" */
     buffer[0] = get_windows_drive();
@@ -2164,6 +2254,46 @@ static void test_FindFirstFileA(void)
     err = GetLastError();
     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
+
+    /* try FindFirstFileA on "test-dir" with forbidden chars */
+    CreateDirectoryA("test-dir", NULL);
+    _lclose(_lcreat("test-file", 0));
+    /* NT gives ERROR_BAD_PATHNAME, other windows versions give ERROR_INVALID_PARAMETER.
+       Use this to detect NT, enabling quirks in below tests. */
+    SetLastError(0xdeadbeaf);
+    handle = FindFirstFileA("test-dir/ ", &data);
+    is_nt = GetLastError() == ERROR_BAD_PATHNAME;
+    if (handle != INVALID_HANDLE_VALUE)
+        /* Should never happen: above call is expected to fail everywhere, which will be detected in below loop. */
+        FindClose(handle);
+    for (i = 0; i < sizeof(disallowed_chars_test_cases) / sizeof(*disallowed_chars_test_cases); i++) {
+        int find_success, test_success, expected_success;
+        const static char *expected;
+        handle = FindFirstFileA(disallowed_chars_test_cases[i].path, &data);
+        find_success = handle != INVALID_HANDLE_VALUE;
+        if (is_nt && disallowed_chars_test_cases[i].broken_in_nt)
+            /* Some test cases succeed on NT, but fail on more recent windows version.
+               We expect wine to fail, but test must accept NT irregularities.
+             */
+            expected_success = 1;
+        else
+            expected_success = disallowed_chars_test_cases[i].expected_success;
+        if (expected_success) {
+            test_success = find_success;
+            expected = "succeed";
+        } else {
+            test_success = !find_success;
+            expected = "fail";
+        }
+        if (disallowed_chars_test_cases[i].not_implemented)
+            todo_wine ok(test_success, "FindFirstFile on %s should %s%s\n", disallowed_chars_test_cases[i].path, expected, is_nt ? " (NT)":"");
+        else
+            ok(test_success, "FindFirstFile on %s should %s%s\n", disallowed_chars_test_cases[i].path, expected, is_nt ? " (NT)":"");
+        if (handle != INVALID_HANDLE_VALUE)
+             ok(FindClose(handle) == TRUE, "Failed to close handle for %s\n", disallowed_chars_test_cases[i].path);
+    }
+    DeleteFileA("test-file");
+    RemoveDirectoryA("test-dir");
 }
 
 static void test_FindNextFileA(void)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c
index 3207720..61a1f86 100644
--- a/dlls/ntdll/path.c
+++ b/dlls/ntdll/path.c
@@ -499,6 +499,7 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext,
 static inline void collapse_path( WCHAR *path, UINT mark )
 {
     WCHAR *p, *next;
+    int stripped = 0;
 
     /* convert every / into a \ */
     for (p = path; *p; p++) if (*p == '/') *p = '\\';
@@ -560,7 +561,12 @@ static inline void collapse_path( WCHAR *path, UINT mark )
     }
 
     /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */
-    while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--;
+    while (p > path + mark && (p[-1] == ' ' || p[-1] == '.' || p[-1] == '>' || p[-1] == '<' || p[-1] == '"')) {
+        stripped = p[-1] != ' ';
+        p--;
+    }
+
+    if (stripped && p[-1] == '\\') p--;
     *p = 0;
 }
 
-- 
1.7.4.1




More information about the wine-patches mailing list