...
Code Block | ||||
---|---|---|---|---|
| ||||
enum { ARRAY_SIZE = 32 }; void func(void) { char dest[ARRAY_SIZE]; char src[ARRAY_SIZE]; size_t i; /* ... */ for (i = 0; src[i] && (i < sizeof(dest)); i++i) { dest[i] = src[i]; } dest[i] = '\0'; /* ... */} |
Compliant Solution (Off-by-One Error)
...
Code Block | ||||
---|---|---|---|---|
| ||||
enum { ARRAY_SIZE = 32 }; void func(void) { char dest[ARRAY_SIZE]; char src[ARRAY_SIZE]; size_t i; /* ... */ for (i = 0; src[i] && (i < sizeof(dest)-1); i++i) { dest[i] = src[i]; } dest[i] = '\0'; /* ... */} |
Noncompliant Code Example (argv
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> int main(int argc, char *argv[]) { /* ... */ char prog_name[128]; strcpy(prog_name, argv[0]); /* ... */return 0; } |
Compliant Solution (argv
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { /* Be prepared for argv[0] to be null. */ const char * const name = (argc && argv[0]) ? argv[0] : ""; char *prog_name = (char *)malloc(strlen(name) + 1); if (prog_name != NULL) { strcpy(prog_name, name); } else { /* Failed to allocate memory - recover Handle error */ } /* ... */return 0; } |
Remember to add a byte to accommodate the null-terminated byte string.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#define __STDC_WANT_LIB_EXT1__ 1 #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { /* Be prepared for argv[0] to be 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 strcpy_s() error */ } } else { /* Failed to allocate memory - recoverHandle error */ } /* ... */return 0; } |
The strcpy_s()
function can be used to copy data to or from dynamically allocated memory or a statically allocated array. If insufficient space is available, strcpy_s()
returns an error.
...
Code Block | ||||
---|---|---|---|---|
| ||||
int main(int argc, char *argv[]) { /* Be prepared for argv[0] to be null. */ const char * const prog_name = (argc && argv[0]) ? argv[0] : ""; size_t prog_size; /* ... */return 0; } |
Noncompliant Code Example (getenv()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
/*#include <stdlib... */ h> #include <string.h> void func(void) { char buff[256]; char *editor = getenv("EDITOR"); if (editor == NULL) { /* EDITOR environment variable not set. */ } else { strcpy(buff, editor); } /* ... */} |
Compliant Solution (getenv()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
/*#include <stdlib... */ h> #include <string.h> void func(void) { char *buff; char *editor = getenv("EDITOR"); if (editor == NULL) { /* EDITOR environment variable not set. */ } else { size_t len = strlen(editor) + 1; buff = (char *)malloc(len); if (buff == NULL) { /* Handle malloc() error */ } memcpy(buff, editor, len); } /* ... */} |
Noncompliant Code Example (sprintf()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char * name; /* initialized externally */ ) { char filename[128]; sprintf(filename, "%s.txt", name); /* Open filename * / } |
However, because the sprintf()
function makes no guarantees regarding the length of the string generated, a sufficiently long string in name
could generate a buffer overflow.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char * name;) /*{ initialized externally */ char filename[128]; sprintf(filename, "%.123s.txt", name); /* Open filename * /} |
Compliant Solution (snprintf()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char * name;) /*{ initialized externally */ char filename[128]; snprintf(filename, sizeof(filename), "%s.txt", name); /* Open filename * /} |
Risk Assessment
Copying NTBS data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.
...
Search for additional vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C Secure Coding Standard | STR03-C. Do not inadvertently truncate a null-terminated byte string STR07-C. Use the bounds-checking interfaces for remediation of existing string manipulation code |
CERT C++ Secure Coding Standard | STR31-CPP. Guarantee that storage for character arrays has sufficient space for character data and the null terminator |
ISO/IEC TR 24772:2013 | String Termination [CJM] Buffer Boundary Violation (Buffer Overflow) [HCB] Unchecked Array Copying [XYW] |
ISO/IEC TS 17961 (Draft) | Using a tainted value to write to an object using a formatted input or output function [taintformatio] |
MITRE CWE | CWE-119, Failure to constrain operations within the bounds of an allocated memory buffer CWE-120, Buffer copy without checking size of input ("classic buffer overflow") CWE-193, Off-by-one error |
...