NNTS.MIGHT
Buffer overflow from possible non null-terminated string
In C and C++, a C string, or a null-terminated string, is a character sequence terminated with a null character (\0). The length of a C string is found by searching for the null character.
The NNTS family of checkers looks for code that uses string manipulation functions with character arrays that are not or may not be null terminated. The NNTS.MIGHT checker looks for code using string manipulation functions in which required information can't be evaluated, such as an argument with an unknown character length.
Vulnerability and risk
The null termination has historically created security problems. For example:
- a null character inserted into a string can truncate it unexpectedly
- it's a common bug not to allocate enough space for the null character or to forget the null
- many programs don't check the length before copying a string to a fixed-size buffer, causing a buffer overflow when it's too long
- the inability to store a null character means that string and binary data needs to be handled by different functions, which can cause problems if the wrong function is used
Mitigation and prevention
To avoid the problem:
- add special code to validate null termination of string buffers if performance constraints permit
- switch to bounded-string manipulation functions like strncpy
- inspect buffer lengths involved in the buffer overrun traceback
Vulnerable code example
int nnts_m_m_2(char * src)
{
char buf[8];
char tgt[1024];
strncpy(buf, src, 3);
strcpy(tgt, buf);
return 0;
}
Klocwork produces a NNTS.MIGHT buffer overflow issue report at line 7 in this example. The character length of the parameter 'src' isn't known, and if the string length of 'src' is equal to or greater than three, the call to strncpy at line 6 will write only three characters to 'buf'. If the stack memory where 'buf' is allocated doesn't have a null termination in it, the call at line 7 will access arrays outside their bounds. If there is a null termination in 'buf', strcpy may still copy uninitialized data into the 'tgt' buffer. This code could possibly result in a buffer overflow, which can cause various significant security problems.
Klocwork would have produced an NNTS.MUST issue report if the character length of 'src' had been known to be equal to or greater than three.
Fixed code example
int nnts_m_m_2(char * src)
{
char buf[8];
char tgt[1024];
strncpy(buf, src, 3);
// ensure null termination
buf[3] = '\0';
strcpy(tgt, buf);
return 0;
}
In the fixed example, a null terminating character is explicitly added to 'buf' on line 8. Since 'buf' could no longer be a non null-terminated string, the issue has been avoided on line 9.
Related checkers
External guidance
- CERT ARR00-C: Understand how arrays work
- CERT ARR30-C: Do not form or use out-of-bounds pointers or array subscripts
- CERT STR03-C: Do not inadvertently truncate a string
- CERT STR32-C: Do not pass a non-null-terminated character sequence to a library function that expects a string
- CERT STR50-CPP: Guarantee that storage for strings has sufficient space for character data and the null terminator
- CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
- CWE-120: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
- CWE-125: Out-of-bounds Read
- CWE-170: Improper Null Termination
- CWE-787: Out-of-bounds Write
- STIG-ID: APP3590.1 Application is vulnerable to buffer overflows
Security training
Application security training materials provided by Secure Code Warrior.
Extension
This checker can be extended. See Tuning C/C++ analysis for more information.