Versions Compared

Key

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

...

Code Block
bgColor#FFCCCC
langc
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
bgColor#ccccff
langc
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
bgColor#FFcccc
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
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
bgColor#FFcccc
langc
/*#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
bgColor#ccccff
langc
/*#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
bgColor#FFcccc
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
#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 StandardSTR03-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 StandardSTR31-CPP. Guarantee that storage for character arrays has sufficient space for character data and the null terminator
ISO/IEC TR 24772:2013String 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 CWECWE-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

...