Versions Compared

Key

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

The C99 [ISO/IEC 9899:1999] C function strtok() is a string tokenization function that takes two arguments: an initial string to be parsed and a const-qualified character delimiter. It returns a pointer to the first character of a token or to a null pointer if there is no token.

The first time strtok() is called, the string is parsed into tokens and a character delimiter. The strtok() function parses the string up to the first instance of the delimiter character, replaces the character in place with a null byte ('\0'), and returns the address of the first character in the token. Subsequent calls to strtok() begin parsing immediately after the most recently - placed null character.

Because strtok() modifies the initial string to be parsed, the string is subsequently unsafe and cannot be used in its original form. If you need to preserve the original string, copy it into a buffer and pass the address of the buffer to strtok() instead of the original string.

...

Code Block
bgColor#FFCCCC
langc

char *token;
char *path = getenv("PATH");

token = strtok(path, ":");
puts(token);

while (token = strtok(0, ":")) {
  puts(token);
}

printf("PATH: %s\n", path);
/* PATH is now just "/usr/bin" */

After the loop ends, path is modified as follows: "/usr/bin\0/bin\0/usr/sbin\0/sbin\0". This is an issue because the local path variable becomes /usr/bin and because the environment variable PATH has been unintentionally changed, which can have unintended consequences. (See rule ENV30-C. Do not modify the object referenced by the return value of certain functions.)

...

In this compliant solution, the string being tokenized is copied into a temporary buffer which buffer that is not referenced after the call to strtok():

Code Block
bgColor#ccccff
langc

char *token;
const char *path = getenv("PATH");
/* PATH is something like "/usr/bin:/bin:/usr/sbin:/sbin" */

char *copy = (char *)malloc(strlen(path) + 1);
if (copy == NULL) {
  /* handle error */
}
strcpy(copy, path);
token = strtok(copy, ":");
puts(token);

while (token = strtok(0, ":")) {
  puts(token);
}

free(copy);
copy = NULL;

printf("PATH: %s\n", path);
/* PATH is still "/usr/bin:/bin:/usr/sbin:/sbin" */

...

The Linux Programmer's Manual (man) page on strtok(3) [Linux 2008] states:

Never use this function. This function modifies its first argument. The identity of the delimiting character is lost. This function cannot be used on constant strings.

...

LDRA tool suite

V. 5.0

can

Can detect violations of this rule with CERT C Rule Pack.

Compass/ROSE

Tool

Version

Checker

Description

Section
Include Page
LDRA_V
LDRA_V
section

602 S

section

Fully

Implemented section

implemented.

Fortify SCA

Section

 

Section
Section

 

 

section

 

Related Vulnerabilities

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

...

CERT C++ Secure Coding Standard: STR06-CPP. Do not assume that strtok() leaves the parse string unchanged

ISO/IEC 9899:19992011 Section 7.2124.5.8, "The strtok function"

MITRE CWE: CWE-464, "Addition of Data Structure Sentineldata structure sentinel"

Bibliography

[Linux 2008] strtok(3)

...