Strings must contain a null-termination character at or before the address of the last element of the array before they can be safely passed as arguments to standard string-handling functions, such as strcpy()
or strlen()
. This is because these These functions, as well as other string-handling functions defined by the C Standard [ISO/IEC 9899:2011], depend on the existence of a null-termination character to determine the length of a string. Similarly, strings must be null-terminated before iterating on a character array where the termination condition of the loop depends on the existence of a null-termination character within the memory allocated for the string, as in the following example:
...
Noncompliant Code Example (strncpy()
)
The standard strncpy()
function does not guarantee that the resulting string is null terminated. If no null character is contained in the first n
characters of the source
array, the result cannot result will not be null-terminated.
In the first noncompliant code example, ntbs
is null-terminated before the call to strncpy()
. However, the subsequent execution of strncpy()
can overwrite the null-termination character.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> enum { NTBS_SIZE = 32 }; void func(voidconst char *source) { char ntbs[NTBS_SIZE]; ntbs[sizeof(ntbs) - 1] = '\0'; strncpy(ntbs, source, sizeof(ntbs)); } |
In the second noncompliant code example, memset()
is used to clear the destination buffer; unfortunately, the third argument incorrectly specifies the size of the destination array [Schwarz 2005]:
| ||||
#include <string.h>
enum { NTBS_SIZE = 32 };
void func(void) {
char ntbs[NTBS_SIZE];
memset(ntbs, 0, sizeof(ntbs) - 1);
strncpy(ntbs, source, sizeof(ntbs) - 1);
} |
Compliant Solution (Truncation)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> enum { NTBS_SIZE = 32 }; void func(voidconst char *source) { char ntbs[NTBS_SIZE]; strncpy(ntbs, source, sizeof(ntbs) - 1); ntbs[sizeof(ntbs) - 1] = '\0'; } |
...
If the intent is to copy without truncation, this example copies the data and guarantees that the resulting null-terminated byte string is null-terminated. If the string cannot be copied, it is handled as an error condition.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> enum { NTBS_SIZE = 32 }; void func(void) { const char *source = "0123456789abcdef";) { char ntbs[NTBS_SIZE]; if (source) { if (strlen(source) < sizeof(ntbs)) { strcpy(ntbs, source); } else { /* Handle string too large condition. */ } } else { /* Handle NULL string condition. */ } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#define __STDC_WANT_LIB_EXT1__ #include <string.h> enum { NTBS_SIZE = 32 }; void func(void) { const char *source = "0123456789abcdef";) { char a[NTBS_SIZE]; if (source) { errno_t err = strncpy_s(a, sizeof(a), source, 5); if (err != 0) { /* Handle error */ } } else { /* Handle NULL string condition. */ } } |
Noncompliant Code Example (realloc()
)
...
[ISO/IEC 9899:2011] | Subclause K.7.1.4, "The strncpy_s function" | [Schwarz 2005] | |
[Seacord 2013] | Chapter 2, "Strings" | ||
[Viega 2005] | Section 5.2.14, "Miscalculated NULL Termination" |
...