https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=57573812ed0beb5c92717a7fcfe665c7b54b5d70

commit 57573812ed0beb5c92717a7fcfe665c7b54b5d70
Author:     Corinna Vinschen <cori...@vinschen.de>
AuthorDate: Fri Jun 27 17:32:32 2025 +0200
Commit:     Corinna Vinschen <cori...@vinschen.de>
CommitDate: Fri Jun 27 17:33:12 2025 +0200

    Cygwin: drop ASCII NUL from invalid DOS filename char transposition table
    
    The mechanism to convert characters invalid in DOS/Windows filenames
    to the Unicode private use area starting at 0xf000 accidentally also
    converts ASCII NUL to the private use area.  That usually doesn't happen,
    but what if the filename contains the 0xf000 character and we want to
    convert it back to multibyte?  In this case the 0xf000 becomes the ASCII
    NUL again, and the resulting string is cut short and does not match with
    the real filename.  This leads to all sorts of problems like the
    inability to unlink the file.
    
    Fix this problem by not marking ASCII NUL as transposable character.
    
    This problem has been introduced by adding code to support abstract
    sockets which may contain a NUL char as part of the socket name.  By
    reverting the ASCII NUL in the transposition tables,
    transform_chars_af_unix has to handle ASCII NUL explicitely now.
    
    Reported-by: Christian Franke <christian.fra...@t-online.de>
    Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258367.html
    Fixes: 7d260cfac42d ("Cygwin: add transform_chars_af_unix helper")
    Signed-off-by: Corinna Vinschen <cori...@vinschen.de>
    
    (cherry picked from commit 61e38a8fe0270797b4c9b9f2e2ce33265d498aac)

Diff:
---
 winsup/cygwin/strfuncs.cc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc
index 66667bdb3a3c..cb7911c6b83d 100644
--- a/winsup/cygwin/strfuncs.cc
+++ b/winsup/cygwin/strfuncs.cc
@@ -23,7 +23,7 @@ details. */
    is affected as well, but we can't transform it as long as we accept Win32
    paths as input. */
 static const WCHAR tfx_chars[] = {
- 0xf000 |   0, 0xf000 |   1, 0xf000 |   2, 0xf000 |   3,
+            0, 0xf000 |   1, 0xf000 |   2, 0xf000 |   3,
  0xf000 |   4, 0xf000 |   5, 0xf000 |   6, 0xf000 |   7,
  0xf000 |   8, 0xf000 |   9, 0xf000 |  10, 0xf000 |  11,
  0xf000 |  12, 0xf000 |  13, 0xf000 |  14, 0xf000 |  15,
@@ -62,7 +62,7 @@ static const WCHAR tfx_chars[] = {
    converting back space and dot on filesystems only supporting DOS
    filenames. */
 static const WCHAR tfx_rev_chars[] = {
- 0xf000 |   0, 0xf000 |   1, 0xf000 |   2, 0xf000 |   3,
+            0, 0xf000 |   1, 0xf000 |   2, 0xf000 |   3,
  0xf000 |   4, 0xf000 |   5, 0xf000 |   6, 0xf000 |   7,
  0xf000 |   8, 0xf000 |   9, 0xf000 |  10, 0xf000 |  11,
  0xf000 |  12, 0xf000 |  13, 0xf000 |  14, 0xf000 |  15,
@@ -109,7 +109,7 @@ transform_chars_af_unix (PWCHAR out, const char *path, 
__socklen_t len)
 {
   len -= sizeof (__sa_family_t);
   for (const unsigned char *p = (const unsigned char *) path; len-- > 0; ++p)
-    *out++ = (*p <= 0x7f) ? tfx_chars[*p] : *p;
+    *out++ = (*p <= 0x7f) ? (*p == 0) ? 0xf000 : tfx_chars[*p] : *p;
   return out;
 }

Reply via email to