Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Removed the memcpy CS, updated CSs to properly check argc; reviewed

...

Code Block
bgColor#ccccff
langc
char dest[ARRAY_SIZE];
char src[ARRAY_SIZE];
size_t i;
/* ... */
for (i=0; src[i] && (i < sizeof(dest)-1); i++) {
  dest[i] = src[i];
}
dest[i] = '\0';
/* ... */

Noncompliant Code Example (argv)

...

Arguments read from the command line are stored in process memory. The function main(), called at program startup, is typically declared as follows when the program accepts command-line arguments:

...

Code Block
bgColor#FFcccc
langc
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

Compliant Solution (argv)

...

The strlen() function can be used to determine the length of the strings referenced by argv[0] through argv[argc-1] so that adequate memory can be dynamically allocated. Note that care must be taken to avoid assuming that argv[0] is non-null.

Code Block
bgColor#ccccff
langc
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 */
  }
  /* ... */
}

Remember to add a byte to accommodate the null-terminated byte string.

Compliant Solution (

...

Annex K, argv)

The strcpy_s() function provides additional safeguards, including accepting the size of the destination buffer as an additional argument. (See STR07-C. Use the bounds-checking interfaces for remediation of existing string manipulation code.) Do not assume that argv[0] is non-null.

Code Block
bgColor#ccccff
langc
#define __STDC_WANT_LIB_EXT1__ 1
#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 - recover */
  }
  /* ... */
}

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.

Compliant Solution (argv) (memcpy())

The C Standard memcpy() function provides a similar capability to strcpy_s() but is universally available. Note that care must be taken to avoid assuming that argv[0] is non-null. Note also that memcpy must not be called with a null pointer even when the second (size) argument is 0.

...

bgColor#ccccff
langc

...

,

...

The memcpy() function differs from strcpy_s() in that it never returns an error. The memcpy() function returns a pointer to the destination string (that is, its first argument). However, memcpy() does not validate that the destination pointer has enough space for the memory being copied and cannot be used if the source and destination strings overlap.

Compliant Solution (argv)

If an argument is not going to be modified or concatenated, there is no reason to make a copy of the string. Not copying a string is the best way to prevent a buffer overflow and is also the most efficient solution. Care must be taken to avoid assuming that argv[0] is non-null.

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

...