sprintf() and size restrictions
OnlineCop

I have a small char array (let's say 10 bytes) that I want to pass into sprintf(). What happens if sprintf() pushes too much onto that array? Here's an example of how to reproduce this:

1#include <iostream>
2 
3int main()
4{
5 int a = 1234;
6 char buffer[10] = {0};
7 
8 // This should be "10"
9 std::cerr << "The size of buffer is: " << sizeof(buffer);
10 
11 // This should be "0"
12 std::cerr << ", and the string length of buffer: " << strlen(buffer);
13 std::cerr << std::endl;
14 
15 // stuff buffer[] with more than 10 chars
16 sprintf(buffer, "I will stuff 'buffer' with lots of text and numbers (like %d)!\n", a);
17 
18 // This should still be "10"
19 std::cerr << "Now the size of buffer is: " << sizeof(buffer);
20 
21 // This results in "65"
22 std::cerr << ", and the string length of buffer is: " << strlen(buffer);
23 std::cerr << std::endl;
24 
25 return 0;
26}

This will crash with a SEGFAULT (so if you run it, do it through a debugger). Apparently, sprintf() is unsafe and "keeps going until it's done" but doesn't do any bounds checking.

Is there a "safe" sprintf() function, like sprintnf() that I can use to ensure that I don't exceed a specified size?

Kitty Cat
Quote:

Apparently, sprintf() is unsafe and "keeps going until it's done" but doesn't do any bounds checking.

Of course, because you don't tell it how big its bounds are (it's not psychic).

Quote:

Is there a "safe" sprintf() function, like sprintnf() that I can use to ensure that I don't exceed a specified size?

snprintf
Or using that other OS that doesn't like to play by everyone else's standards: _snprintf or sprintf_s.

OnlineCop

Perfect. Thanks, KC!

Thomas Fjellstrom

I personally like using the return value of snprintf, and passing NULL to the string arg so it just calculates the total length, and then allocating a properly sized buffer to do it again.

Another option is to use GCC's asprintf. It allocates the buffer for you.

Goalie Ca

Uhh... you're using iostream and sprintf? Why???

Use #include <strstream>

bamccaig
Thomas Fjellstrom said:

I personally like using the return value of snprintf, and passing NULL to the string arg so it just calculates the total length, and then allocating a properly sized buffer to do it again.

O_o

    char* buf = NULL;
    int len = 0;

    len = snprintf(buf, 0, "foo");
    buf = (char*)malloc(len+1);
    len = snprintf(buf, len, "foo");

???

Thomas Fjellstrom
    char* buf = NULL;
    int len = 0;

    len = snprintf(buf, 0, "foo");
    buf = (char*)malloc(len);
    len = snprintf(buf, len, "foo");

pretty much, though I'd do it like so:

    char* buf = NULL;
    int len = 0;

    len = snprintf(NULL, 0, "foo");
    buf = (char*)malloc(len+1);
    snprintf(buf, len, "foo");

Just to be obvious about the NULL bit.

BAF

Stringstream = better.

OnlineCop

Is there a sprintf()-style function available for std::string? If so, you wouldn't need to worry about memory allocation/deallocation or string length.

Does std::stringstream allow you to do this?

LennyLen
Quote:

Stringstream = better.

Though you get problems trying to use it in C. ;)

BAF

OnlineCop: yes.

Thread #595278. Printed from Allegro.cc