"C library functions such as strcpy
(), strcat (), sprintf () and vsprintf
() operate on null terminated strings
and perform no bounds checking."
"snprintf is safer than sprintf"
What do these statements really mean?
char* msg1 = new char[10];
strcpy(msg1, "test"); // 1
char buffer[128];
sprintf(buffer, "%s", msg); //2
char* msg1 = new char[10];
strncpy(msg1, "test", 4);
// you can also use 5 here, which will copy also the null character, since this is 4 the remaining characters will be filled with nulls
char buffer[128];
snprintf(buffer, "%s", msg, 10);
// This will copy 10 bytes from the source to the destination, if the null character is encountered before 10, same as sprintf, if not 11 th character onwards will be filled with null.... However if the call was snprintf(buffer, "%s", msg, 128); and the 128th character is not null, that's it, the buffer has a non-null terminated c-string. For sprintf, it'll try to read the destination until it encounters a null and copy to the destination.
This won't work with char pointers though.
char* pBuf = new char[100]; // sizeof(pBuf) = 8
char buffer[100]; // sizeof(buffer) = 100
There's a nice little hack that you can you to find the exact buffer size you need by calling snprintf twice. Like so,
"snprintf is safer than sprintf"
What do these statements really mean?
int sprintf( char *str, const char *format, ... )
int snprintf ( char * s, size_t n, const char * format, ... );
char * strcpy ( char * destination, const char * source );
char * strncpy ( char * destination, const char * source, size_t num );
The usage is something like;char* msg1 = new char[10];
strcpy(msg1, "test"); // 1
char buffer[128];
sprintf(buffer, "%s", msg); //2
strcpy : Copies bytes until it finds a 0-byte in the source code. The string literal "test" has 4 characters and a terminating null character at end, therefore needs 5 characters at least on msg1.
Is this dangerous? Yes, because if the source message is not null terminated it will read until a null character is encountered and write to the destination, and the buffer might over-run.
strncpy : Copies only the specified number of bytes from the source to the destination. If the null character is encountered before reading the n bytes from source, all the remaining bytes in destination will be filled with null.... but if the null character is not encountered, the strncpy will just not append a null character. Therefore you might end up with non-null terminated string if you use this.
This is the exact same story with sprintf vs snprintf.
sprinf depends on the null terminated character while the snprintf doesn't.
Is this really dangerous?
msg1 [*|*|*|*|*|*|*|*|*|*] => This
buffer may overflow regardless it being in the stack or heap. If it's
the heap you might get a segmentation fault, if it is in stack you might
end up with unexpected results due to corrupted stack values.
The safer usage is therefore;
char* msg1 = new char[10];
strncpy(msg1, "test", 4);
// you can also use 5 here, which will copy also the null character, since this is 4 the remaining characters will be filled with nulls
char buffer[128];
snprintf(buffer, "%s", msg, 10);
// This will copy 10 bytes from the source to the destination, if the null character is encountered before 10, same as sprintf, if not 11 th character onwards will be filled with null.... However if the call was snprintf(buffer, "%s", msg, 128); and the 128th character is not null, that's it, the buffer has a non-null terminated c-string. For sprintf, it'll try to read the destination until it encounters a null and copy to the destination.
Therefore
you must ensure that your buffer size is at least 1 character longer
than the source format you pass. If you pass the exact number of bytes in source, and if the source has more than that many bytes left, it will be filled with nulls. Otherwise you must take care of the null character by yourself.
If you are using the n-versions, still you have to correctly specify the n value such that it's not more than that of the source buffer length but you are protected against unintentional overflows due to null character not being present. However you should make sure that you give the correct number of bytes to be copied, if not that's your fault ;-)
One way is to use sizeof operator;
char buffer[100];
snprintf(buffer, sizeof(buffer), "This is a %.4s\n", "testGARBAGE DATA");
char* pBuf = new char[100]; // sizeof(pBuf) = 8
char buffer[100]; // sizeof(buffer) = 100
There's a nice little hack that you can you to find the exact buffer size you need by calling snprintf twice. Like so,
int length = snprintf(NULL, 0, "This is a %.4s\n", "testGARBAGE DATA");
++length; // +1 for null terminator
char buffer = malloc(length);
snprintf(buffer, length, "This is a %.4s\n", "testGARBAGE DATA");
Comments
Post a Comment