3 ms·
HN, Help! Before I dive into this, does anyone know whether this affects the argument parsing in Cygwin, that prepares the arguments for a regular int main(int
by kazinator 2y ago
HN, Help! Before I dive into this, does anyone know whether this affects the argument parsing in Cygwin, that prepares the arguments for a regular int main(int argc, char *argv)?
TXR Lisp uses wchar_t strings, and the "W" functions on Windows. So that's well and good. But it does start with a regular C main, relying on the Cygwin run-time for that.
If that's vulnerable, I will hack it to have its own argument parsing, using the wide char command line.
Maybe I should ask this on the Cygwin mailing list.
- shakna 2y agoCygwin has been using the W variant of most things. [0] Unfortunately, they're using it on "__argv", not "__wargv". Which means they are probably vulnerable to this. [0] https://cygwin.com/cgit/newlib-cygwin/tree/winsup/cygwin/kernel32.cc#n417 https://cygwin.com/cgit/newlib-cygwin/tree/winsup/cygwin/ker...
- cryptonector 2y agoStarting with main() instead of wmain() is enough to make it vulnerable :(
- kazinator 2y agoIt's enough to make it suspicious, but there is a way for a C compiler on Windows to support regular main startup such that it is not vulnerable. It depends on which/whose piece of code takes the WCHAR-based command line and produces the char-based argv[]. Does that code do the "WorstFit" thing, or not. In my program, I could fix it (if necessary) by taking the WCHAR command line and parsing it myself, using my own UTF8 encoding routines to make the multi-byte strings.
- cryptonector 2y agoYes, that's what I'd do: write a `wmain()` that converts UTF-16 arguments to UTF-8 then calls the real `main()` (which you'll have to rename).
- kazinator 2y agoExcept, in the Cygwin ecosystem, it doesn't look as if you can do that. All the "crt" stuff for setting up the executable environment is built around regular main. Luckily, I maintain a fork of the Cygwin DLL for my project called Cygnal, where I can make improvements. The focus has not been security up to now, but rather restoring some "native like" behaviors in the Cygwin run-time that are "too POSIXy" for native Windows users. I could hack the CRT stuff in the Cygnal fork to avoid pitfalls in producing the main() arguments. At the moment, I only looked at this issue fairly superficially, so I don't have a full picture of how what piece are doing exactly what in this area.
- kazinator 2y agoTo close this loose end in the HN thread: The above guess turns out to be false. You can link a program in Cygwin that has WinMain. If you don't include <windows.h>, you can give it whatever argument list you like, such as (void), and it will work. But in 32 bit Cygwin (which I still support), it will complain about _WinMain@16 missing (as a warning only). If you give it the correct signature declared in <winbase.h> then it links on 32 or 64 bit Cygwin just fine. without warnings. In this WinMain, you can use the wide-string functions for obtaining the command line and parsing to arguments. I am going with this fix for TXR.
- kazinator 2y agoLooks like this is unnecessary. Cygwin in fact uses GetCommandLineW and does its own parsing. See reply by Corinna Vinschen: https://cygwin.com/pipermail/cygwin/2025-January/257074.html https://cygwin.com/pipermail/cygwin/2025-January/257074.html
- kazinator 2y agoCygwin evidently contains its own versions of certain Win32 functions, like in this source file: https://github.com/cygwin/cygwin/blob/main/winsup/cygwin/kernel32.cc https://github.com/cygwin/cygwin/blob/main/winsup/cygwin/ker... If we jump to the very bottom, we see that GetCommandLineA is one of the functions implemented in this file. It uses something called RtlUnicodeStringToAnsiString. Microsoft declares that one in <wdm.h> and places it in NTOSKRNL.EXE. That very function is mentioned in the submitted article as having the problem! If Cygwin handles arguments through this function in preparation for main(), and it's the Microsoft one, it has the issue.