...
Code Block | ||||
---|---|---|---|---|
| ||||
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) { dest[i] = src[i]; } dest[i] = '\0'; } |
...
Command-line arguments are passed to main()
as pointers to null-terminated byte strings in the array members argv[0]
through argv[argc - 1]
. If the value of argc
is greater than 0, the string pointed to by argv[0]
is, by convention, the program name. If the value of argc
is greater than 1, the strings referenced by argv[1]
through argv[argc - 1]
are the actual program arguments.
Vulnerabilities can occur when inadequate space is allocated to copy a command-line argument or other program input. In this noncompliant code example, the contents of argv[0]
can be manipulated by an attacker to cause a buffer overflow:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#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 {
/* Handle error */
}
free(prog_name);
return 0;
}
|
Remember to add a byte to accommodate the null-terminated byte string.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#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 error */
}
} else {
/* Handle error */
}
free(prog_name);
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 | ||||
---|---|---|---|---|
| ||||
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()
)
The getenv()
function searches an searches the environment list, provided by the host environment, for a string that matches the string pointed to by name
. The set of environment names and the method for altering the environment list are implementation-defined. Environment variables can be arbitrarily large, and copying them into fixed-length arrays without first determining the size and allocating adequate storage can result in a buffer overflow.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#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 error */
}
memcpy(buff, editor, len);
free(buff);
}
}
|
Noncompliant Code Example (sprintf()
)
...