In compilers on Unix-based OSes and MinGW/MSYS2 on Windows, function asprintf
is the version of function sprintf
with security enhancements. That is because asprintf
allocates the buffer with sufficient size for the string.
char *str = NULL;
asprintf (&str, "%s", "hello, world");
...
free (str);
However, Microsoft does not implement this function in MSVC. Instead, Microsoft implements sprintf_s
from MSVC 2005. Unlike asprintf
, sprintf_s
does not allocate the buffer with sufficient size for the string. It requires an extra argument for buffer size:
char *str = (char *)calloc (100, sizeof (char));
sprintf_s (str, 100, "%s", "hello, world");
...
free (str);
The purpose of these two functions is to avoid buffer overflow. But asprintf
can completely avoid buffer overflow, while sprintf_s
cannot. If someone uses a large integer for the buffer size argument in function sprintf_s
, buffer overflow can still happen. For example:
char *str1 = (char [100]){""}, *str2 = (char [100]){""};
...
sprintf_s (str1, 200, "%s\n%s", str2, "hello, world");
...
Similarly, scanf
family functions in compilers on Unix-based OSes and MinGW/MSYS2 on Windows support the m
specifier for security enhancements:
char *str = NULL;
scanf ("%m[^\n]", &str);
...
free (str);
But MSVC implements scanf_s
family functions requiring an extra argument for buffer size:
char *str = (char *)calloc (100, sizeof (char));
scanf_s ("%[^\n]", str, 100);
...
free (str);
Actually, the m
specifier can completely avoid buffer overflow, but function scanf_s
in MSVC cannot. For example:
char *str = (char *)calloc (100, sizeof (char));
scanf_s ("%[^\n]", str, 200);
...
free (str);
So why does Microsoft not choose to use dynamic allocation of the buffer with sufficient size for input string to avoid buffer overflow, but using an extra argument for buffer size instead in MSVC from MSVC 2005? (The former method can completely avoid buffer overflow, but the latter one cannot)
NB: _s
functions are NOT in C standard until C11. Microsoft started to implement them from MSVC 2005.
CodePudding user response:
Quoth the docs for asprintf
, emphasis mine:
CONFORMING TO:
These functions are GNU extensions, not in C or POSIX. They are also available under *BSD. The FreeBSD implementation sets strp to NULL on error.
IOW, because MSVC isn't GNU, and doesn't implement that GNU extension to the C standard library.
MingW/MSYS use the GNU C Standard Library, which does implement the function.
CodePudding user response:
sprintf_s()
is in the C standard optional Annex K.
asprintf()
is not in the C spec.
Implementing asprintf()
is not needed to make a compliant C compiler/library.
MSVC implements sprintf_s()
, yet not properly with the type of the size parameter.