...
Code Block | ||
---|---|---|
| ||
char *path = getenv("PATH"); /* PATH is something like "/usr/bin:/bin:/usr/sbin:/sbin" */ char *token; token = strtok(path, ":"); puts(token); while (token = strtok(0, ":")) { puts(token); } printf("PATH: %s\n", path); /* PATH is now just "/usr/bin" */ |
In this example, the {{ Wiki Markup strtok()
}} function is used to parse the first argument into colon-delimited tokens; it will output each word from the string on a new line. However, after the while loop ends, path
\[\] will have been modified to look like this: {{"/usr/bin\0/bin\0/usr/sbin\0/sbin\0"
}}. This is an issue on several levels. If we check our local {{path
}} variable, we will only see {{/usr/bin
}} now. Even worse, we have changed the environment variable PATH, which could cause more confusion (see
ENV30-C. Do not modify the string returned by getenv()).
Compliant Solutions
One possible solution is to copy the string being tokenized into a temporary buffer which isn't referenced after the calls to strtok()
:
Code Block | ||
---|---|---|
| ||
char string[]*path = "Hello secure coding wiki!"; char buff[256]getenv("PATH"); /* PATH is something like "/usr/bin:/bin:/usr/sbin:/sbin" */ char *copy = malloc(strlen(path) + 1); strcpy(copy, path); char *token; strncpy(buff, string); token = strtok(buffcopy, ' '":"); puts(token); while (token = strtok(NULL0, ' '":")) { puts(token); } printf("PATH: %s\n", path); /* furtherPATH stringis manipulation on string[] succeedsstill "/usr/bin:/bin:/usr/sbin:/sbin" */ |
Another possibility is to provide your own implementation of strtok()
which does not modify the initial arguments.
...