msvcrt alternative for MinGW? (e.g. to get conforming snprintf)

南笙酒味 提交于 2021-01-27 12:52:47

问题


So here's a fun one...

we have a few C libraries which should be platform independent, even though they were developed on linux, because they only rely on the c standard library as defined in ISO/IEC 9899:1999. When we compiled those libraries with MinGW everything seemed to work fine at first, but today we found out that the snprintf() implementation of msvcrt is braindea... sorry, i meant "incompatible" with the definition in the C99 standard.

I would have expected a warning from MinGW, telling me that -std=c99 actually isn't fully supported. Because otherwise, how am i supposed to know?

Is there any alternative c standard library for windows, and most importantly: can MinGW somehow be told to link against it instead of msvcrt?

If not, we would at the very least need a list or something where we can check for other potential portability problems concerning msvcrt and c99.

PS: I know about Cygwin and MSYS2, but i'd rather have native windows binaries (in part because we also use our libraries in Matlab).

Edit: Sorry, i should have explained more clearly what exactly my problem with msvcrt's snprintf() is. According to the standard, snprintf() is required to output a '\0' as the last character, if the output doesn't fit. However, msvcrt just doesn't do that, so the resulting string is no longer properly terminated. I have no idea why anyone would choose to implement snprintf() that way, because to me just omitting the '\0' doesn't make any sense at all.

We have also tried the suggested __USE_MINGW_ANSI_STDIO, but i guess that just fixes the missing format specifiers? At least it didn't seem to make a difference for our specific problem.


回答1:


The standard enforces snprintf to behave like this:

Otherwise, output characters beyond the n-1st are discarded rather than being written to the array, and a null character is written at the end of the characters actually written into the array.

snprintf in msvcrt is indeed not the standard one, but a Microsoft version as explained here:
Is snprintf() ALWAYS null terminating?

The following code gives non-compliant results:

#include <stdio.h>

int main (void)
{
  char dst[3];
  snprintf(dst, 3, "%c%c%c", 'A', 'B', 'C');

  for(size_t i=0; i<3; i++)
  {
    printf("%.2X ", dst[i]);
  }
}

I get output 41 42 43 which is not standard compliant. To get standard C, you have to add this before the stdio.h include:

#define __USE_MINGW_ANSI_STDIO 1

And now you get 41 42 00 which is compliant.

The root of all these program security problems is Microsoft, who have been using non-compliant C libs in their products for the past 20 years.




回答2:


If you need C99 stdio from MinGW-w64, you can define __USE_MINGW_ANSI_STDIO so that you bypass the msvcrt implementation. It's best to define this through a compiler argument

-D__USE_MINGW_ANSI_STDIO

Alternatively, you could try to use a MinGW-w64 build that is set up to link with the new ucrt, but I don't know of any pre-existing easy-to-use stable builds that are set up that way.



来源:https://stackoverflow.com/questions/57604482/msvcrt-alternative-for-mingw-e-g-to-get-conforming-snprintf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!