Hi, Bertrand Garrigues via wrote on Mon, Oct 12, 2020 at 01:42:49AM +0200:
> I've just pushed an update of the 'gnulib' and added this point > to the 'FOR-RELEASE' file. A major problem with gnulib emerged just now that we should perhaps treat as a blocker. I'm still gathering information about the details, so please regard what i'm say here as a preliminary understanding. The problem is not new with respect to groff nor with respect to gnulib, but it is becoming more severe because several operating systems strive to improve security with respect to printf(3). OpenBSD developers have only been aware that that it affects groff for a relatively short time. The code in gnulib/lib/vasnprintf.c line 4879 puts a format string containing a %n directive into writeable memory and subsequently passes that memory as a first argument to printf(3). Using %n at all is insecure programming practice. Having printf(3) format strings in writeable memory (as opposed to in RODATA sections) is slightly insecure programming practice. Having %n in format strings stored in writeable memory is highly insecure programming practice, so much so that some operating systems already abort programs doing that, most notably Mac OS X 10.13 or newer. More operation systems will soon start doing the same, for example OpenBSD, most likely next week or so. The way gnulib detects whether to compile that code seems to be very broken. On the one hand, gnulib performs extremely complex tests that resemble an (overly aggressive) regression suite rather than mere feature tests. If i understand correctly, if *anything* in that suite fails, no matter whether it's important or just a very weird corner case, gnulib tends to compile the file gnulib/lib/vasnprintf.c. On the other hand, that file does lots of very complicated version number and operating system name tests on its own at compile time rather than at ./configure time, so it is very difficult to figure out what is actually happening, and even more so to check whether what is happening in a specific compilation run is correct. For example, it appears that one among large numbers of effects that can trigger compilation of gnulib/lib/vasnprintf.c is that the operating system denies %n in writeable memory, and as a consequence gnulib/lib/vasnprintf.c is compiled and then proceeds to use %n in writeable memory. If i understand correctly, that is quite an absurd effect: the %n feature ends up getting used precisely *because* it crashes the program. Even if these specific issues could be solved, i would not feel comfortable using gnulib/lib/vasnprintf.c. It is about three times the size of a reasonable printf(3) implementation, and it is riddled with 552 preprocessor directive lines: $ grep '^#' gnulib/lib/vasnprintf.c | sed 's/\# */\#/;s/ .*//' \ | sort | uniq -c | sort -nr 181 #endif 170 #if 71 #else 60 #define 30 #include 22 #undef 11 #ifndef 7 #elif So that 5621-line file, with a preprocessor directive every ten lines on average, is practically impossible to audit for correctness, even if one wanted to. The ./bootstrap.conf in our root directory says: gnulib_modules=" ... fprintf-posix snprintf vsnprintf " While i did rarely run into operating systems that failed to provide the non-standard function vasprintf(3) - a GNU extension also available in all BSDs - groff does not use that function. I do not remember ever running into a system lacking any of the standard functions * fprintf(3) - first appeared in Version 7 AT&T UNIX * snprintf(3) and vsnprintf(3) - first in 4.4BSD So my favourite solution would be to just stop using all the gnulib *printf* modules. I'm not aware of any portability problems they might help to solve, not even on historic systems like Solaris 9, but they most definitly cause severe portability and security issues on several operating systems, in particular on modern ones. What do you think? Should i do testing without these three modules on OpenBSD, Linux, and various versions of Solaris to see if that improves matters? Yours, Ingo