Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Minor edits, removed an NCCE that was superfluous; reviewed

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
bgColor#FFcccc
langc
#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]:

code
bgColor#FFcccc
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
#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"

...