OverflowTruncationSufficiency
From C
Terms
Overflow
When the sprintf
function writes a
sequence of bytes to a destination of insufficient allocated
length, overflow occurs. Put on your rain coat.
Truncation
When the (so-called "safe") snprintf
function
attempts to write a sequence of bytes, and the number of which
is greater than the maximum length specified by the user, the
number of bytes written to the destination are truncated to
the maximum length.
Sufficiency
Somehow obtaining knowledge of the number of bytes that will be written
to the desintation, before allocating the destintation itself,
allows one always to allocate sufficient space before commencing
the write operation with sprintf
or
snprintf
.
Do not rely on so-called "safe" functions so blindly
This page is meant to discuss the use of so-called "safe" functions like strncpy, snprintf, etc.
Imagine that your bank uses only "safe" functions like snprintf(). Doesn't that make you feel all warm and fuzzy?
#include <stdio.h> int main(void) { char amount[7]; snprintf(amount, sizeof amount, "%d", 1000000); puts(amount); return 0; }
The main point is that while swapping sprintf() for snprintf() may eliminate buffer overflow, it doesn't make your program any "safer". Doing proper input checking is still required -- there is no magic shortcut around it.
Using sufficiency instead of truncation
Sanity checking the length of your data is very good practise.
Unfortunately, there are some cases where one might not know the
length of the output of sprintf
to dest
.
One may lose (assumingly) valuable data in the name of false
--even the warm, fuzzy feeling-- safety, if snprintf
is used unwisely.
One should always be able to allocate sufficient space before commencing the write. Such as in the code below:
#include <stdlib.h> #include <stdio.h> int main(void) { char *amount; size_t len; int num = 1000000; len = snprintf(NULL, 0, "%d", num); amount = malloc(len + 1); if (amount != NULL) { snprintf(amount, len + 1, "%d", num); printf("string: %s\n" "length was: %d\n", amount, len); free(amount); } return 0; }
(Failure-checks added for correctness.)
Program output:
string: 1000000 length was: 7