I am currently, writing a code for string manipulation.
As part of this, I am using vsnprintf().
However, compiler flashes below error message:
dont_call: vsnprintf(). Invokation of a potentially dangerous function
that could introduce a vulnerability. remediation:
Recommendation: Use vsprintf_s() instead!
The results with vsprintf_s() is as not expected.
What is the difference between vsnprintf() and vsprintf_s()?
vsnprintf()is a perfectly fine standard function that has no security issues if used properly, especially if the format string is a string literal compatible with the arguments passed.Microsoft deprecated this function because an attacker could take advantage of sloppy code that uses user supplied text as the format specification: carefully crafted user supplied strings could use the
%nformat to try and corrupt the program's data and make the program execute arbitrary code.Using a variable format string is error prone as it is difficult to verify that the types of the arguments are compatible with this dynamically generated format string. Sensible coding conventions do not permit such code. Passing a user supplied string as a format string is completely inappropriate as it is a trivial source of undefined behavior. Disabling useful and standard functions because they could be misused and create security flaws is laudable, but in this particular case, the proposed alternatives have shortcomings.
There are 2 alternatives for
vsnprintf(), standardized in Annex K, but with optional support and thus non portable across environments:and
These functions behave differently from
vsnprintfin subtile ways:%nspecifier.nto have a0value.starget array to be a null pointer, whichsnprintf()allows if thensize is0.vsprintf_sdiffers fromvsnprintf_swhen the output string is longer thann-1: it sets the destination to the empty string, invokes the error handler and returns0or a negative number instead of the length of the formatted string, as bothvsnprintfandvsnprintf_sdo.As commented by A T, to make matters worse, Microsoft implements different semantics in their own version of this standard functions: even the prototype for
vsnprintf_sis different (as documented in the Visual Studio documentation):As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable.
You did not post the code where you want a replacement for
snprintf(), but a classic use case is this:In the above code,
vnsprintfcannot be replaced withvsprintf_sbecausevsprintf_scannot be used to compute the required size: it always considers a short size as an error.vsnprintf_scannot be used as a direct replacement because it considers aNULLpointer as the target to be an error too.The solution is simple: you can prevent Visual Studio from emitting this warning by defining a macro before including
<stdio.h>in the source file:This prevents the warning for all deprecated library functions.
Note also that it is very useful to increase the warning level and let the compiler warn about potential bugs, such as inconsistent arguments for a given format string. With
gccandclang, you can pass-Walland other command line options to enable such behavior. For Visual Studio, you can add more warnings with/W4.