Hello!

snprintf() function in mingw-w64 is broken. Seems that it just calls
MSVC's _snprintf() function which is not same as snprintf(). MSVC until
ucrt does not provide snprintf() at all, just _snprintf().

Differences are that MSVC's _snrpintf() does not ensure that filled
buffer would be null-termed and when overflow occurs it returns -1
instead of length which is needed to fully format string.

See following example:

  #include <stdio.h>

  int main() {
    char buf[5] = "XXXX";
    int ret = snprintf(buf, 3, "%d", 123456789);
    printf("buf=%s ret=%d\n", buf, ret);
    return 0;
  }

It prints:

  buf=123X ret=-1

So for MSVC's _snprintf() it is needed to write wrapper, e.g. following:

  #define snprintf(str, size, format, ...) ( (((size_t)(size) > 0) ? 
(_snprintf((str), (size), (format), __VA_ARGS__), ((char 
*)str)[(size_t)(size)-1] = 0, 0) : 0), _scprintf((format), __VA_ARGS__) )

It is simple inline-able macro so it does not increase executable code
size too much.

MSVC's _scprintf() function returns length of formatted string, so
exactly what snprintf() return value should be.

With that snprintf() define, output of above example is:

  buf=12 ret=9

Which is correct now.

Would you consider fixing snprintf() in mingw-w64?

Similarly also vsnprintf() can be fixed:

  #define vsnprintf(str, size, format, ap) ( (((size_t)(size) > 0) ? 
(_vsnprintf((str), (size), (format), (ap)), ((char *)str)[(size_t)(size)-1] = 
0, 0) : 0), _vscprintf((format), (ap)) )

-- 
Pali Rohár
pali.ro...@gmail.com

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to