Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47766 Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/kernelbase/path.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 3defaf3965..465778f2a1 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -276,13 +276,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** continue; }
- /* Keep the . if one of the following is true: - * 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS - * 2. in form of a..b - */ - if (dst > buffer - && (((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS) && dst[-1] != '\') - || (dst[-1] != '\' && src[2] != '\' && src[2]))) + /* Keep the .. if not surrounded by \ */ + if ((src[2] != '\' && src[2]) || (dst > buffer && dst[-1] != '\')) { *dst++ = *src++; *dst++ = *src++; @@ -313,14 +308,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** } else { - /* Keep the . if one of the following is true: - * 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS - * 2. in form of a.b, which is used in domain names - * 3. *. - */ - if (dst > buffer - && ((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS && dst[-1] != '\') - || (dst[-1] != '\' && src[1] != '\' && src[1]) || (dst[-1] == '*'))) + /* Keep the . if not surrounded by \ */ + if ((src[1] != '\' && src[1]) || (dst > buffer && dst[-1] != '\')) { *dst++ = *src++; continue; @@ -352,6 +341,20 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** /* End the path */ *dst = 0;
+ /* Strip multiple trailing . */ + if (!(flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS)) + { + while (dst > buffer && dst[-1] == '.') + { + if (dst - 1 > buffer && dst[-2] == '*') + break; + else if (dst - 1 > buffer && dst[-2] == ':' && dst - 2 == root_end) + *--dst = '\'; + else + *--dst = 0; + } + } + /* If result path is empty, fill in \ */ if (!*buffer) {
From: Zhiyi Zhang zzhang@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47766 Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/kernelbase/tests/path.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index b5da303629..d7492a1e9f 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -72,6 +72,7 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"\\?C:a", "\\?C:a", 0, S_OK},
/* No . */ + {"*", "*", 0, S_OK}, {"", "\", 0, S_OK}, {"C:", "C:", 0, S_OK}, {"C:\", "C:\", 0, S_OK}, @@ -85,17 +86,26 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"*.", "*.", 0, S_OK}, {"*..", "*.", 0, S_OK}, {"*...", "*.", 0, S_OK}, + {"*....", "*.", 0, S_OK}, + {".a", ".a", 0, S_OK}, {"a.", "a", 0, S_OK}, + {".a.", ".a", 0, S_OK}, {"a.b", "a.b", 0, S_OK}, + {".a.b.", ".a.b", 0, S_OK}, {"a\.", "a", 0, S_OK}, {"a\.\b", "a\b", 0, S_OK}, + {":.", ":", 0, S_OK}, {"C:.", "C:\", 0, S_OK}, + {"C:.\", "C:.\", 0, S_OK}, + {"C:.\.", "C:\", 0, S_OK}, {"C:\.", "C:\", 0, S_OK}, {"C:\.\", "C:\", 0, S_OK}, {"C:\a.", "C:\a", 0, S_OK}, + {"C:\.a", "C:\.a", 0, S_OK}, {"C:\a\.", "C:\a", 0, S_OK}, {"C:\a\\.", "C:\a\", 0, S_OK}, {"C:\a\\\.", "C:\a\\", 0, S_OK}, + {".\", "\", 0, S_OK}, {"\.", "\", 0, S_OK}, {"\\.", "\\", 0, S_OK}, {"\\.\", "\\", 0, S_OK}, @@ -115,21 +125,42 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = "\\?\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\", 0, S_OK},
/* .. */ + {"..a", "..a", 0, S_OK}, + {"...a", "...a", 0, S_OK}, + {"....a", "....a", 0, S_OK}, {"a..", "a", 0, S_OK}, + {"a...", "a", 0, S_OK}, + {"a....", "a", 0, S_OK}, + {"..a..", "..a", 0, S_OK}, {"a..b", "a..b", 0, S_OK}, + {"..a..b..", "..a..b", 0, S_OK}, {"a\..", "\", 0, S_OK}, {"a\..\", "\", 0, S_OK}, {"a\..\b", "\b", 0, S_OK}, + {":..", ":", 0, S_OK}, {"C:..", "C:\", 0, S_OK}, + {"C:...", "C:\", 0, S_OK}, + {"C:..\", "C:..\", 0, S_OK}, + {"C:..\\", "C:..\\", 0, S_OK}, + {"C:...\", "C:...\", 0, S_OK}, {"C:\..", "C:\", 0, S_OK}, + {"C:\..a", "C:\..a", 0, S_OK}, + {"C:\...a", "C:\...a", 0, S_OK}, + {"C:\....a", "C:\....a", 0, S_OK}, + {"C:\a..", "C:\a", 0, S_OK}, {"C:\\..", "C:\", 0, S_OK}, {"C:\..\", "C:\", 0, S_OK}, + {"C:\...\", "C:\...\", 0, S_OK}, {"C:\a\..", "C:\", 0, S_OK}, + {"C:\a\b..", "C:\a\b", 0, S_OK}, {"C:\a\\..", "C:\a", 0, S_OK}, {"C:\a\\\..", "C:\a\", 0, S_OK}, {"C:\a\..\b", "C:\b", 0, S_OK}, {"C:\a\..\\b", "C:\\b", 0, S_OK}, + {"..\", "\", 0, S_OK}, + {"...\", "...\", 0, S_OK}, {"\..", "\", 0, S_OK}, + {"\...", "\", 0, S_OK}, {"\\..", "\\", 0, S_OK}, {"\\\..", "\", 0, S_OK}, {"\\..\", "\\", 0, S_OK}, @@ -249,6 +280,8 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] =
/* PATHCCH_DO_NOT_NORMALIZE_SEGMENTS */ /* No effect for spaces */ + {"a ", "a ", 0, S_OK}, + {"C:\a ", "C:\a ", 0, S_OK}, {"C:\a \", "C:\a \", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:\a\ ", "C:\a\ ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:\a ", "C:\a ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, @@ -265,6 +298,7 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"..", "\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:.", "C:.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:..", "C:..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, + {"C:...", "C:...", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:\a\.", "C:\a", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:\a\..", "C:\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK}, {"C:\a.", "C:\a.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, S_OK},
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47766 Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/kernelbase/tests/path.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index d7492a1e9f..0a4295deef 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -84,16 +84,24 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"..", "\", 0, S_OK}, {"...", "\", 0, S_OK}, {"*.", "*.", 0, S_OK}, + {"*.\", "*.\", 0, S_OK}, {"*..", "*.", 0, S_OK}, + {"*..\", "*..\", 0, S_OK}, {"*...", "*.", 0, S_OK}, + {"*...\", "*...\", 0, S_OK}, {"*....", "*.", 0, S_OK}, + {"*....\", "*....\", 0, S_OK}, {".a", ".a", 0, S_OK}, + {".a\", ".a\", 0, S_OK}, {"a.", "a", 0, S_OK}, + {"a.\", "a.\", 0, S_OK}, {".a.", ".a", 0, S_OK}, {"a.b", "a.b", 0, S_OK}, {".a.b.", ".a.b", 0, S_OK}, {"a\.", "a", 0, S_OK}, {"a\.\b", "a\b", 0, S_OK}, + {"a\.b", "a\.b", 0, S_OK}, + {"a\.b\", "a\.b\", 0, S_OK}, {":.", ":", 0, S_OK}, {"C:.", "C:\", 0, S_OK}, {"C:.\", "C:.\", 0, S_OK}, @@ -101,7 +109,9 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"C:\.", "C:\", 0, S_OK}, {"C:\.\", "C:\", 0, S_OK}, {"C:\a.", "C:\a", 0, S_OK}, + {"C:\a.\", "C:\a.\", 0, S_OK}, {"C:\.a", "C:\.a", 0, S_OK}, + {"C:\.a\", "C:\.a\", 0, S_OK}, {"C:\a\.", "C:\a", 0, S_OK}, {"C:\a\\.", "C:\a\", 0, S_OK}, {"C:\a\\\.", "C:\a\\", 0, S_OK}, @@ -126,11 +136,16 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] =
/* .. */ {"..a", "..a", 0, S_OK}, + {"..a\", "..a\", 0, S_OK}, {"...a", "...a", 0, S_OK}, + {"...a\", "...a\", 0, S_OK}, {"....a", "....a", 0, S_OK}, {"a..", "a", 0, S_OK}, + {"a..\", "a..\", 0, S_OK}, {"a...", "a", 0, S_OK}, + {"a...\", "a...\", 0, S_OK}, {"a....", "a", 0, S_OK}, + {"a....\", "a....\", 0, S_OK}, {"..a..", "..a", 0, S_OK}, {"a..b", "a..b", 0, S_OK}, {"..a..b..", "..a..b", 0, S_OK}, @@ -145,9 +160,13 @@ static const struct alloccanonicalize_test alloccanonicalize_tests[] = {"C:...\", "C:...\", 0, S_OK}, {"C:\..", "C:\", 0, S_OK}, {"C:\..a", "C:\..a", 0, S_OK}, + {"C:\..a\", "C:\..a\", 0, S_OK}, {"C:\...a", "C:\...a", 0, S_OK}, + {"C:\...a\", "C:\...a\", 0, S_OK}, {"C:\....a", "C:\....a", 0, S_OK}, + {"C:\....a\", "C:\....a\", 0, S_OK}, {"C:\a..", "C:\a", 0, S_OK}, + {"C:\a..\", "C:\a..\", 0, S_OK}, {"C:\\..", "C:\", 0, S_OK}, {"C:\..\", "C:\", 0, S_OK}, {"C:\...\", "C:\...\", 0, S_OK},
This is an alternative solution to the one submitted by Zhiyi Zhang. The second patch in this series contains the tests from Zhiyi Zhang's patch. The third patch contains additional tests, including some that do not pass using Zhiyi Zhang's patch.
-- Jeff
-- Jeff
On Wed, Sep 18, 2019 at 12:12 PM Jeff Smith whydoubt@gmail.com wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47766 Signed-off-by: Jeff Smith whydoubt@gmail.com
dlls/kernelbase/path.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 3defaf3965..465778f2a1 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -276,13 +276,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** continue; }
/* Keep the . if one of the following is true:
* 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
* 2. in form of a..b
*/
if (dst > buffer
&& (((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS) && dst[-1] != '\\')
|| (dst[-1] != '\\' && src[2] != '\\' && src[2])))
/* Keep the .. if not surrounded by \ */
if ((src[2] != '\\' && src[2]) || (dst > buffer && dst[-1] != '\\')) { *dst++ = *src++; *dst++ = *src++;
@@ -313,14 +308,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** } else {
/* Keep the . if one of the following is true:
* 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
* 2. in form of a.b, which is used in domain names
* 3. *.
*/
if (dst > buffer
&& ((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS && dst[-1] != '\\')
|| (dst[-1] != '\\' && src[1] != '\\' && src[1]) || (dst[-1] == '*')))
/* Keep the . if not surrounded by \ */
if ((src[1] != '\\' && src[1]) || (dst > buffer && dst[-1] != '\\')) { *dst++ = *src++; continue;
@@ -352,6 +341,20 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** /* End the path */ *dst = 0;
- /* Strip multiple trailing . */
- if (!(flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS))
- {
while (dst > buffer && dst[-1] == '.')
{
if (dst - 1 > buffer && dst[-2] == '*')
break;
else if (dst - 1 > buffer && dst[-2] == ':' && dst - 2 == root_end)
*--dst = '\\';
else
*--dst = 0;
}
- }
- /* If result path is empty, fill in \ */ if (!*buffer) {
-- 2.21.0
Hi Jeff,
Thanks for the work. Your approach is cleaner and cover more test cases. I made a little modification to your patch to handle . after : better and merged the tests. I hope that is ok with you.
v2 should supersede 169985~169987 and 169977.
Thanks, Zhiyi
On 9/19/19 1:12 AM, Jeff Smith wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47766 Signed-off-by: Jeff Smith whydoubt@gmail.com
dlls/kernelbase/path.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 3defaf3965..465778f2a1 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -276,13 +276,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** continue; }
/* Keep the . if one of the following is true:
* 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
* 2. in form of a..b
*/
if (dst > buffer
&& (((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS) && dst[-1] != '\\')
|| (dst[-1] != '\\' && src[2] != '\\' && src[2])))
/* Keep the .. if not surrounded by \ */
if ((src[2] != '\\' && src[2]) || (dst > buffer && dst[-1] != '\\')) { *dst++ = *src++; *dst++ = *src++;
@@ -313,14 +308,8 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** } else {
/* Keep the . if one of the following is true:
* 1. PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
* 2. in form of a.b, which is used in domain names
* 3. *.
*/
if (dst > buffer
&& ((flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS && dst[-1] != '\\')
|| (dst[-1] != '\\' && src[1] != '\\' && src[1]) || (dst[-1] == '*')))
/* Keep the . if not surrounded by \ */
if ((src[1] != '\\' && src[1]) || (dst > buffer && dst[-1] != '\\')) { *dst++ = *src++; continue;
@@ -352,6 +341,20 @@ HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR ** /* End the path */ *dst = 0;
- /* Strip multiple trailing . */
- if (!(flags & PATHCCH_DO_NOT_NORMALIZE_SEGMENTS))
- {
while (dst > buffer && dst[-1] == '.')
{
if (dst - 1 > buffer && dst[-2] == '*')
break;
else if (dst - 1 > buffer && dst[-2] == ':' && dst - 2 == root_end)
*--dst = '\\';
else
*--dst = 0;
}
- }
- /* If result path is empty, fill in \ */ if (!*buffer) {