Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [Seacord 2013b]. To prevent such errors, either limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the character data to be copied and the null-termination character. (see See STR03-C. Do not inadvertently truncate a string.).
When strings live on the heap, this rule is a specific instance of MEM35-C. Allocate sufficient memory for an object. Because strings are represented as arrays of characters, this rule is related to both ARR30-C. Do not form or use out-of-bounds pointers or array subscripts and ARR38-C. Guarantee that library functions do not form invalid pointers.
...
The C Standard, Annex K [ISO/IEC 9899:2011], states:
No additional characters are read after a new-line character (which is discarded) or after end-of-file. The discarded new-line character does not count towards number of characters read. A null character is written immediately after the last character read into the array.
...
The getline()
function is similar to the fgets()
function but can dynamically allocate memory for the input buffer. If passed a null pointer, getline()
dynamically allocates a buffer of sufficient size to hold the input. If passed a pointer to dynamically allocated storage that is too small to hold the contents of the string, the getline()
function resizes the buffer, using realloc()
, rather than truncating the input. If successful, the getline()
function returns the number of characters read, which can be used to determine if the input has any null characters before the newline. The getline()
function works only with dynamically allocated buffers. Allocated memory must be explicitly deallocated by the caller to avoid memory leaks. (see See MEM31-C. Free dynamically allocated memory when no longer needed.).
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <string.h> void func(void) { int ch; size_t buffer_size = 32; char *buffer = malloc(buffer_size); if (!buffer) { /* Handle error */ return; } if ((ssize_t size = getline(&buffer, &buffer_size, stdin)) == -1) { /* Handle error */ } else { char *p = strchr(buffer, '\n'); if (p) { *p = '\0'; } else { /* Newline not found; flush stdin to end of line */ while ((ch = getchar()) != '\n' && ch != EOF) ; if (ch == EOF && !feof(stdin) && !ferror(stdin)) { /* Character resembles EOF; handle error */ } } } free (buffer); } |
...
The strcpy_s()
function provides additional safeguards, including accepting the size of the destination buffer as an additional argument. (see See STR07-C. Use the bounds-checking interfaces for string manipulation.).
Code Block | ||||
---|---|---|---|---|
| ||||
#define __STDC_WANT_LIB_EXT1__ 1 #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { /* Ensure argv[0] is not null */ const char *const name = (argc && argv[0]) ? argv[0] : ""; char *prog_name; size_t prog_size; prog_size = strlen(name) + 1; prog_name = (char *)malloc(prog_size); if (prog_name != NULL) { if (strcpy_s(prog_name, prog_size, name)) { /* Handle error */ } } else { /* Handle error */ } /* ... */ free(prog_name); return 0; } |
...
According to the C Standard, 7.22.4.6 [ISO/IEC 9899:2011]:
The
getenv
function searches an environment list, provided by the host environment, for a string that matches the string pointed to byname
. The set of environment names and the method for altering the environment list are implementation defined.
...
In this noncompliant code example, name
refers to an external string; it could have originated from user input, from the file system, or from the network. The program constructs a file name from the string in preparation for opening the file.
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
STR31-C | High | Likely | Medium | P18 | L1 |
Automated Detection
Array access out of bounds, Buffer overflow from incorrect string format specifier, Destination buffer overflow in string manipulation, Invalid use of standard library string routine, Missing null in string array, Pointer access out of bounds, Tainted NULL or non-null-terminated string, Use of dangerous standard function
Tool | Version | Checker | Description | |||||||
---|---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| LANG.MEM.BO | Buffer overrun | |||||||
|
| Can detect violations of the rule. However, it is unable to handle cases involving | ||||||||
Coverity | 6.5 | STRING_OVERFLOW | Fully implemented | |||||||
5.0 |
|
| ||||||||
| NNTS.TAINTED |
| ||||||||
| 489 S, 109 D, 66 X, 70 X, 71 X | Partially implemented | ||||||||
Parasoft C/C++test | 9.5 | BD-PB-OVERFWR,SECURITY-12 | ||||||||
Polyspace Bug Finder | R2016a | Guarantee that storage for strings has sufficient space for character data and null terminator | ||||||||
|
|
| ||||||||
PRQA QA-C |
| warncall for 'gets' | Partially implemented |
...