snprintf
This function requires a specified length, and the compiler will perform an out-of-bounds check, so it must be ensured that the target length is longer than the sum of all parameters. But consider the following procedure:
#include <stdio.h>
#include <string.h>
#define LENGTH 1024
int main() {
char cache[LENGTH];
memset(cache, 0, LENGTH);
snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
return 0;
}
After opening this program-Wall
, an error will be reported:
test.c: In function ‘main’:
test.c:9:44: error: ‘/ruaruarua’ directive output truncated writing 10 bytes into a region of size 4 [-Werror=format-truncation=]
snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
~~~~^~~~~~
test.c:9:5: note: ‘snprintf’ output 11 or more bytes into a destination of size 4
snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
This error is expected because it is indeed possible to cross the boundary. So the question is, how can I complete the same function without reporting an error?
My gcc
version is relatively new, 7.1.1
. It is estimated that older versions of the compiler will not report this error.
PHP中文网2017-05-27 17:46:46
First of all, the second parameter of snprintf()
represents the size of the buffer, here it should be LENGTH
, the value of sizeof(LENGTH)
is 4
(I guess what you want to write should be sizeof (cache)
bar). So, will it be OK after changing it to snprintf(cache, LENGTH, "%s/ruaruarua", cache);
? Let’s look at this example:
#include <stdio.h>
int main()
{
char buf[20] = "hello";
snprintf(buf, 20, "%s world", buf);
puts(buf);
return 0;
}
This example attempts to add a string to the end of buf
, take a look at the output
world
Did not achieve the desired results. Why is this? There is this paragraph in the manual of snprintf()
:
Some programs imprudently rely on code such as the following
sprintf(buf, "%s some further text", buf);
to append text to
buf
. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when callingsprintf()
,snprintf()
,vsprintf()
, andvsnprintf( )
. Depending on the version ofgcc(1)
used, and the compiler options employed, calls such as the above will not produce the expected results.That is, if the original and destination buffers overlap, the execution results of these
printf()
family functions will be undefined.
So how do you "print your original content and some new content into an array"? One way is to set the buffer passed to snprintf()
to the end of the string in the array:
snprintf(buf + strlen(buf), 20, " world");
Then how to continuously add data to the end of the buffer? Notice that the function return value of the printf()
family is the number of characters printed (number of characters printed), then you can call it like this:
#include <stdio.h>
#include <string.h>
int main()
{
char buf[40];
char *p = buf;
p += sprintf(p, "hello %s\n", "world");
p += sprintf(p, "hello %s", "again");
/* and more similar calls... */
puts(buf);
return 0;
}
The result is
hello world
hello again