...
Arguments read from the command line and 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 | ||
---|---|---|
| ||
int main(int argc, char *argv[]) {
/* ... */
char * prog_name = (char *)malloc(strlen(argv[0])+1);
if (prog_name != NULL) {
strcpy(prog_name, argv[0]);
}
else {
/* Couldn't get the memory - recover */
}
/* ... */
}
|
...
While the above example is secure, the more generic case where the source string is changeable is vulnerable to a TOCTOU race condition.
Code Block | ||
---|---|---|
| ||
ccharchar * copy_string(const char * src) { /* ... */ char * dest = (char *)malloc(strlen(src)+1); if (dest != NULL) { strcpy(dest, src); } else { /* Couldn't get the memory - recover */ } /* ... */ } |
...
Compliant Solution ( memcpy()
)
The memcpy()
function operates in principle just like can provide the same functionality for this example as strcpy_s()
, but is more universally available.
Code Block | ||
---|---|---|
| ||
int main(int argc, char *argv[]) {
/* ... */
char * prog_name;
size_t prog_size;
prog_size = strlen(argv[0])+1;
prog_name = (char *)malloc(prog_size);
if (prog_name != NULL) {
memcpy(prog_name, argv[0], prog_size);
}
else {
/* Couldn't get the memory - recover */
}
/* ... */
}
|
The memcpy()
function differs from {[strcpy_s()
}} in that it never returns an error. It always returns a pointer to the destination string, e.g. its first argument. However, memcpy()
does not validate that the destination pointer has enough space for the memory being copied. And it should not be used if the source and destination strings overlap.
...