On 2025-05-10 Pali Rohár wrote:
> Just cosmetic comment: It seems that this file uses coding style which
> put { on a new line after while keyword and also put two spaces
> before {.

Thanks! I attached an updated patch that has this fixed.

The first if-statement in the file already has { on the same line. I
didn't modify that. There's also some inconsistency between "char *foo"
and "char* foo".

-- 
Lasse Collin
>From b15762687956b985a4575fe5e90bf8273f453245 Mon Sep 17 00:00:00 2001
From: Lasse Collin <lasse.col...@tukaani.org>
Date: Thu, 8 May 2025 16:20:05 +0300
Subject: [PATCH v2 6/7] crt: stat: Don't remove a trailing '\' if it is a DBCS
 trail byte

In double-byte character sets, the trail byte of a two-byte character
can be a backslash. If such a two-byte character was at the end of
the pathname, the trailing backslash was incorrectly removed.

The code still removes only one trailing directory separator and thus
stat("directory//", &st) still incorrectly fails with MSVCRT. This
commit only fixes the DBCS issue.
---
 mingw-w64-crt/stdio/__mingw_fix_stat_path.c | 36 ++++++++++++++++++---
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/mingw-w64-crt/stdio/__mingw_fix_stat_path.c 
b/mingw-w64-crt/stdio/__mingw_fix_stat_path.c
index 7614491a9..b853d1d1e 100644
--- a/mingw-w64-crt/stdio/__mingw_fix_stat_path.c
+++ b/mingw-w64-crt/stdio/__mingw_fix_stat_path.c
@@ -4,10 +4,22 @@
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
 
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
 #include <sys/stat.h>
 #include <stdlib.h>
+#include <locale.h>
+#include <windows.h>
 #include "__mingw_fix_stat.h"
 
+static const char* next_char (unsigned int cp, const char* p)
+{
+  /* If it is a lead byte, skip the next byte except if it is \0.
+   * If it is \0, it's not a valid DBCS string. */
+  return (IsDBCSLeadByteEx (cp, *p) && p[1] != '\0') ? p + 2 : p + 1;
+}
+
 /**
  * Returns _path without trailing slash if any
  *
@@ -20,6 +32,7 @@
 
 char* __mingw_fix_stat_path (const char* _path)
 {
+  const unsigned int cp = __mingw_filename_cp ();
   size_t len;
   char *p;
 
@@ -28,24 +41,27 @@ char* __mingw_fix_stat_path (const char* _path)
   if (_path && *_path) {
     len = strlen (_path);
 
-    /* Ignore X:\ */
-
+    /* Ignore X:\
+     * No ANSI or OEM code page uses ':' as a trail byte. (The code page 1361
+     * cannot be used as ANSI or OEM code page.) */
     if (len <= 1 || ((len == 2 || len == 3) && _path[1] == ':'))
       return p;
 
+    const char *r = _path;
+
     /* Check UNC \\abc\<name>\ */
     if ((_path[0] == '\\' || _path[0] == '/')
        && (_path[1] == '\\' || _path[1] == '/'))
       {
-       const char *r = &_path[2];
+       r = &_path[2];
        while (*r != 0 && *r != '\\' && *r != '/')
-         ++r;
+         r = next_char (cp, r);
        if (*r != 0)
          ++r;
        if (*r == 0)
          return p;
        while (*r != 0 && *r != '\\' && *r != '/')
-         ++r;
+         r = next_char (cp, r);
        if (*r != 0)
          ++r;
        if (*r == 0)
@@ -54,6 +70,16 @@ char* __mingw_fix_stat_path (const char* _path)
 
     if (_path[len - 1] == '/' || _path[len - 1] == '\\')
       {
+       /* Return if the last character is a double-byte character.
+        * Its trail byte could be a '\' which must not be interpret
+        * as a directory separator. */
+       while (r[1] != '\0')
+         {
+           r = next_char (cp, r);
+           if (*r == '\0')
+             return p;
+         }
+
        p = (char*)malloc (len);
        if (p == NULL)
          return NULL; /* malloc has set errno. */
-- 
2.49.0

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to