By accident I had still some left-over directories from some test run, and tried a recursive dir in the wineprefix. That led to the ASan report below.
[Testbot run with this patch](https://testbot.winehq.org/JobDetails.pl?Key=161037)
<details> <summary>ASan report with gdb session</summary>
``` $ wine cmd /K "cd /d c:"
c:>dir c:\tmp.txt /s Datenträger in Laufwerk c hat keine Bezeichnung. Datenträgernummer ist 4300-0000
Directory of c:
16.10.2025 22:48 5,925,244 tmp.txt 1 file 5,925,244 bytes ================================================================= ==520==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffffe1ddea8 at pc 0x00014001a9e9 bp 0x7ffffe1dd270 sp 0x7ffffe1dd2b8 WRITE of size 2 at 0x7ffffe1ddea8 thread T0 #0 0x00014001a9e8 in lstrcatW .../wine/include/winbase.h:2615 #1 0x00014001b8c9 in WCMD_list_directory .../wine/programs/cmd/directory.c:276 #2 0x00014001c7e3 in WCMD_list_directory .../wine/programs/cmd/directory.c:509 #3 0x00014001c7e3 in WCMD_list_directory .../wine/programs/cmd/directory.c:509 ... #23 0x00014001c7e3 in WCMD_list_directory .../wine/programs/cmd/directory.c:509 #24 0x00014001c7e3 in WCMD_list_directory .../wine/programs/cmd/directory.c:509 #25 0x00014001a525 in WCMD_directory .../wine/programs/cmd/directory.c:1000 #26 0x000140023e97 in WCMD_run_builtin_command .../wine/programs/cmd/wcmdmain.c:2244 #27 0x00014002964d in execute_single_command .../wine/programs/cmd/wcmdmain.c:2393 #28 0x0001400288ef in node_execute .../wine/programs/cmd/wcmdmain.c:4597 #29 0x00014002aba6 in wmain .../wine/programs/cmd/wcmdmain.c:4948 #30 0x000140037fec in wmainCRTStartup .../wine/dlls/msvcrt/crt_wmain.c:60 #31 0x6fffffc67a54 in BaseThreadInitThunk (C:\windows\system32\kernel32.dll+0x178027a54) #32 0x6fffffde06d6 in RtlUserThreadStart (C:\windows\system32\ntdll.dll+0x1700506d6)
Address 0x7ffffe1ddea8 is located in stack of thread T0 at offset 2920 in frame #0 0x00014001b59f in WCMD_list_directory .../wine/programs/cmd/directory.c:242
This frame has 8 object(s): [32, 2080) 'string' (line 244) [2208, 2272) 'datestring' (line 244) [2304, 2368) 'timestring' (line 244) [2400, 2920) 'real_path' (line 245) <== Memory access at offset 2920 overflows this variable [3056, 3064) 'ft' (line 247) [3088, 3104) 'st' (line 248) [3120, 3168) 'username' (line 338) [3200, 3792) 'finddata' (line 465) HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp, SEH and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow .../wine/include/winbase.h:2615 in lstrcatW ... ==520==ABORTING
$ gdb-multiarch -q --pid $(pidof 'C:\windows\system32\cmd.exe') (gdb) b ReportError (gdb) b ReportGenericError (gdb) handle SIGSEGV nostop noprint (gdb) handle SIGUSR1 nostop noprint (gdb) cont (gdb) set osabi Windows (gdb) bt #0 ReportGenericError () at /home/runner/work/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_report.cpp:516 #1 0x00006ffffe8d7857 in __asan_report_store2 () at /home/runner/work/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:134 #2 0x000000014001a9e9 in lstrcatW (dst=<optimized out>, src=<optimized out>) at .../wine/include/winbase.h:2615 #3 0x000000014001b8ca in WCMD_list_directory (inputparms=0x7ef45afe0e50, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:276 #4 0x000000014001c7e4 in WCMD_list_directory (inputparms=0x7ef45afe0e20, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:509 #5 0x000000014001c7e4 in WCMD_list_directory (inputparms=0x7ef45afe0df0, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:509 ... #25 0x000000014001c7e4 in WCMD_list_directory (inputparms=0x7ef45afe02e0, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:509 #26 0x000000014001c7e4 in WCMD_list_directory (inputparms=0x7ef45afe0220, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:509 #27 0x000000014001a526 in WCMD_directory (args=<optimized out>) at .../wine/programs/cmd/directory.c:1000 #28 0x0000000140023e98 in WCMD_run_builtin_command (cmd_index=8, cmd=0x7f405b008200 L"dir c:\tmp.txt /s") at .../wine/programs/cmd/wcmdmain.c:2244 #29 0x000000014002964e in execute_single_command (command=<optimized out>) at .../wine/programs/cmd/wcmdmain.c:2393 #30 0x00000001400288f0 in node_execute (node=<optimized out>) at .../wine/programs/cmd/wcmdmain.c:4597 #31 0x000000014002aba7 in wmain (argc=<optimized out>, argvW=<optimized out>) at .../wine/programs/cmd/wcmdmain.c:4948 #32 0x0000000140037fed in wmainCRTStartup () at .../wine/dlls/msvcrt/crt_wmain.c:60 #33 0x00006fffffc67a55 in BaseThreadInitThunk () from .../wine-build/llvm-old64-asan-pe/obj/dlls/kernel32/x86_64-windows/kernel32.dll #34 0x00006fffffde06d7 in RtlUserThreadStart () from .../wine-build/llvm-old64-asan-pe/obj/dlls/ntdll/x86_64-windows/ntdll.dll #35 0x0000000000000000 in ?? () (gdb) up (gdb) up (gdb) up #3 0x000000014001b8ca in WCMD_list_directory (inputparms=0x7ef45afe0e50, level=<optimized out>, outputparms=<optimized out>) at .../wine/programs/cmd/directory.c:276 276 lstrcatW(real_path, parms->fileName); (gdb) set print elements 0 (gdb) print parms->dirName $1 = (WCHAR *) 0x7f1a5afe9080 L"c:\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\abcdefghij\" (gdb) print parms->fileName $2 = (WCHAR *) 0x7ef25afe0bf0 L"tmp.txt" (gdb) print sizeof(real_path)/sizeof(*real_path) $3 = 260 ```
</details>
-- v2: cmd: Skip directories if they exceed MAX_PATH in WCMD_list_directory (ASan).
From: Bernhard Übelacker bernhardu@mailbox.org
--- programs/cmd/directory.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c index 0fb9ad7fdd6..0839e32cbe7 100644 --- a/programs/cmd/directory.c +++ b/programs/cmd/directory.c @@ -269,6 +269,14 @@ static RETURN_CODE WCMD_list_directory (DIRECTORY_STACK *inputparms, int level, parms = inputparms; fd = xalloc(sizeof(WIN32_FIND_DATAW)); while (parms && lstrcmpW(inputparms->dirName, parms->dirName) == 0) { + + if ((lstrlenW(parms->dirName) + lstrlenW(parms->fileName) + 1) > ARRAY_SIZE(real_path)) { + WINE_TRACE("Path gets too long: '%s' '%s'\n", wine_dbgstr_w(parms->dirName), wine_dbgstr_w(parms->fileName)); + /* Move to next parm */ + parms = parms->next; + continue; + } + concurrentDirs++;
/* Work out the full path + filename */
v2: - if it gets too long, skip directory instead of allocating more memory.
Behaves like native with these commands: ``` $ LANG=C wine cmd /K "c:"
c:>mkdir c:\1234567890\1234567890
c:>echo test > c:\1234567890\1234567890\123456789012345678901234567890.txt
c:>rename c:\1234567890\1234567890 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 12345678901234567890123412345678901234567890
c:>dir c:\1234567890\123456789012345678901234567890.txt /s Volume in drive c has no label. Volume Serial Number is 4300-0000
File not found.
c:>rename c:\1234567890\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 234567890123412345678901234567890 1234567890
c:>del c:\1234567890\1234567890\123456789012345678901234567890.txt
c:>rmdir c:\1234567890\1234567890
c:>rmdir c:\1234567890
c:> ```
On Tue Nov 25 14:21:29 2025 +0000, eric pouech wrote:
IIRC native doesn't support paths longer than MAX_PATH characters (everywhere, not only in DIR command) even relative paths are first transformed into absolute, and dropped if larger than MAX_PATH so we need to skip this entry rather than dynamically allocate the buffer
Thanks for having a look, I changed it to skip it when it gets too long in v2.
This merge request was approved by eric pouech.