Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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 functions, as well as other string-handling functions defined by C99 by the C standard [ISO/IEC 9899:19992011], 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:

Code Block
langc

size_t i;
char ntbs[16];
/* ... */
for (i = 0; i < sizeof(ntbs); ++i) {
  if (ntbs[i] == '\0') break;
  /* ... */
}

...

The standard strncpy() function does not guarantee that the resulting string is null terminated [ISO/IEC 9899:19992011]. If there is no null character is containded in the first n characters of the source array, the result could 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
bgColor#FFcccc
langc

char ntbs[NTBS_SIZE];

ntbs[sizeof(ntbs)-1] = '\0';
strncpy(ntbs, source, sizeof(ntbs));

...

Code Block
bgColor#FFcccc
langc

char ntbs[NTBS_SIZE];

memset(ntbs, 0, sizeof(ntbs)-1);
strncpy(ntbs, source, sizeof(ntbs)-1);

...

Code Block
bgColor#ccccff
langc

char ntbs[NTBS_SIZE];

strncpy(ntbs, source, sizeof(ntbs)-1);
ntbs[sizeof(ntbs)-1] = '\0';

...

Code Block
bgColor#ccccff
langc

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 */
}

...

The strncpy_s() function copies up to n characters from the source array to a destination array [ISO/IEC TR 24731-1:2007]. If no null character was copied from the source array, then the nth position in the destination array is set to a null character, guaranteeing that the resulting string is null-terminated.

Code Block
bgColor#ccccff
langc

char *source;
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 */
}

...

The following noncompliant code example fails to ensure that cur_msg is properly null-terminated:

Code Block
bgColor#ffcccc
langc

char *cur_msg = NULL;
size_t cur_msg_size = 1024;

/* ... */

void lessen_memory_usage(void) {
  char *temp;
  size_t temp_size;

  /* ... */

  if (cur_msg != NULL) {
    temp_size = cur_msg_size/2 + 1;
    temp = realloc(cur_msg, temp_size);
    if (temp == NULL) {
      /* Handle error condition */
    }
    cur_msg = temp;
    cur_msg_size = temp_size;
  }
}

/* ... */

Because realloc() does not guarantee that the string is properly null-terminated, any subsequent operation on cur_msg that assumes a null-termination character may result in undefined behavior.

...

In this compliant solution, the lessen_memory_usage() function ensures that the resulting string is always properly null-terminated.

Code Block
bgColor#ccccff
langc

char *cur_msg = NULL;
size_t cur_msg_size = 1024;

/* ... */

void lessen_memory_usage(void) {
  char *temp;
  size_t temp_size;

  /* ... */

  if (cur_msg != NULL) {
    temp_size = cur_msg_size/2 + 1;
    temp = realloc(cur_msg, temp_size);
    if (temp == NULL) {
      /* Handle error condition */
    }
    cur_msg = temp;
    cur_msg_size = temp_size;

    /* ensure string is null-terminated */
    cur_msg[cur_msg_size - 1] = '\0';
  }
}

/* ... */

Risk Assessment

Failure to properly null-terminate strings can result in buffer overflows and the execution of arbitrary code with the permissions of the vulnerable process. Null-termination errors can also result in unintended information disclosure.

...

section

Fully

Implemented

implemented.

Compass/ROSE

can

Can detect some violations of this rule

section

.

NNTS

Tool

Version

Checker

Description

LDRA tool suite

Include Page
LDRA_V
LDRA_V
section

600 S

Section
Section

 

 

Section

Klocwork

Include Page
Klocwork_V
Klocwork_V
Section

 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

...

CERT C++ Secure Coding Standard: STR32-CPP. Null-terminate character arrays as required

ISO/IEC 9899:19992011 Section 7.1.1, "Definitions of terms," Section 7.2022.3.4 5, "The realloc function," and Section 7.2124, "String handling <string.h>"

ISO/IEC TR 24772 "CJM String Terminationtermination"

ISO/IEC TR 24731-1:2007 Section 6.7.1.4, "The strncpy_s function"

MITRE CWE: CWE-119, "Failure to Constrain Operations constrain operations within the Bounds bounds of an Allocated Memory Bufferallocated memory buffer"

MITRE CWE: CWE-170, "Improper Null Terminationnull termination"

Bibliography

[Schwarz 2005]
[Seacord 2005a] Chapter 2, "Strings"
[Viega 2005] Section 5.2.14, "Miscalculated NULL termination"

...