Home  >  Q&A  >  body text

linux - How to use snprintf to print the original content and some new content into an array?

snprintfThis 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.

仅有的幸福仅有的幸福2723 days ago841

reply all(1)I'll reply

  • PHP中文网

    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 calling sprintf(), snprintf(), vsprintf(), and vsnprintf( ). Depending on the version of gcc(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

    reply
    0
  • Cancelreply