From: Dmitry V. Levin Date: Sun, 25 Mar 2012 21:49:48 +0000 (+0000) Subject: Robustify parsing of numbers from strings X-Git-Tag: v4.7~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ccee169ab6aa4ae7515198dadcef5dd2286ede4b;p=strace Robustify parsing of numbers from strings * defs.h (string_to_uint): New prototype. * util.c (string_to_uint): New function. * strace.c (error_opt_arg): New function. (process_opt_p_list): Use string_to_uint instead of atoi. Terminate in case of invalid process id. (init): Use string_to_uint instead of atoi. Use error_opt_arg in case of invalid option argument. * syscall.c (qual_syscall, qual_signal, qual_desc): Use string_to_uint instead of atoi. --- diff --git a/defs.h b/defs.h index e46e230a..33484003 100644 --- a/defs.h +++ b/defs.h @@ -489,6 +489,8 @@ extern const char *getfdpath(struct tcb *, int); extern const char *xlookup(const struct xlat *, int); +extern int string_to_uint(const char *str); + #if HAVE_LONG_LONG /* _l refers to the lower numbered u_arg, * _h refers to the higher numbered u_arg diff --git a/strace.c b/strace.c index ac7e6720..c211ac73 100644 --- a/strace.c +++ b/strace.c @@ -131,7 +131,7 @@ static uid_t run_uid; static gid_t run_gid; unsigned int max_strlen = DEFAULT_STRLEN; -static unsigned int acolumn = DEFAULT_ACOLUMN; +static int acolumn = DEFAULT_ACOLUMN; static char *acolumn_spaces; static char *outfname = NULL; @@ -315,6 +315,12 @@ void die_out_of_memory(void) error_msg_and_die("Out of memory"); } +static void +error_opt_arg(int opt, const char *arg) +{ + error_msg_and_die("Invalid -%c argument: '%s'", opt, arg); +} + /* Glue for systems without a MMU that cannot provide fork() */ #ifdef HAVE_FORK # define strace_vforked 0 @@ -825,14 +831,14 @@ process_opt_p_list(char *opt) char c = *delim; *delim = '\0'; - pid = atoi(opt); /* TODO: stricter parsing of the number? */ + pid = string_to_uint(opt); if (pid <= 0) { - error_msg("Invalid process id: '%s'", opt); + error_msg_and_die("Invalid process id: '%s'", opt); *delim = c; return; } if (pid == strace_tracer_pid) { - error_msg("I'm sorry, I can't let you do that, Dave."); + error_msg_and_die("I'm sorry, I can't let you do that, Dave."); *delim = c; return; } @@ -905,6 +911,7 @@ startup_attach(void) if (de->d_fileno == 0) continue; + /* we trust /proc filesystem */ tid = atoi(de->d_name); if (tid <= 0) continue; @@ -1445,7 +1452,7 @@ static void __attribute__ ((noinline)) init(int argc, char *argv[]) { struct tcb *tcp; - int c; + int c, i; int optF = 0; struct sigaction sa; @@ -1547,9 +1554,9 @@ init(int argc, char *argv[]) not_failing_only = 1; break; case 'a': - acolumn = atoi(optarg); + acolumn = string_to_uint(optarg); if (acolumn < 0) - error_msg_and_die("Bad column width '%s'", optarg); + error_opt_arg(c, optarg); break; case 'e': qualify(optarg); @@ -1558,7 +1565,10 @@ init(int argc, char *argv[]) outfname = strdup(optarg); break; case 'O': - set_overhead(atoi(optarg)); + i = string_to_uint(optarg); + if (i < 0) + error_opt_arg(c, optarg); + set_overhead(i); break; case 'p': process_opt_p_list(optarg); @@ -1570,10 +1580,10 @@ init(int argc, char *argv[]) } break; case 's': - max_strlen = atoi(optarg); - if (max_strlen < 0) { - error_msg_and_die("Invalid -%c argument: '%s'", c, optarg); - } + i = string_to_uint(optarg); + if (i < 0) + error_opt_arg(c, optarg); + max_strlen = i; break; case 'S': set_sortby(optarg); @@ -1586,10 +1596,9 @@ init(int argc, char *argv[]) die_out_of_memory(); break; case 'I': - opt_intr = atoi(optarg); - if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) { - error_msg_and_die("Invalid -%c argument: '%s'", c, optarg); - } + opt_intr = string_to_uint(optarg); + if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) + error_opt_arg(c, optarg); break; default: usage(stderr, 1); diff --git a/syscall.c b/syscall.c index c4ac9778..cf9cd082 100644 --- a/syscall.c +++ b/syscall.c @@ -338,7 +338,7 @@ qual_syscall(const char *s, int bitflag, int not) int rc = -1; if (*s >= '0' && *s <= '9') { - int i = atoi(s); + int i = string_to_uint(s); if (i < 0 || i >= MAX_QUALS) return -1; qualify_one(i, bitflag, not, -1); @@ -375,7 +375,7 @@ qual_signal(const char *s, int bitflag, int not) int i; if (*s >= '0' && *s <= '9') { - int signo = atoi(s); + int signo = string_to_uint(s); if (signo < 0 || signo >= MAX_QUALS) return -1; qualify_one(signo, bitflag, not, -1); @@ -402,7 +402,7 @@ static int qual_desc(const char *s, int bitflag, int not) { if (*s >= '0' && *s <= '9') { - int desc = atoi(s); + int desc = string_to_uint(s); if (desc < 0 || desc >= MAX_QUALS) return -1; qualify_one(desc, bitflag, not, -1); diff --git a/util.c b/util.c index e57f46ae..ea3488d4 100644 --- a/util.c +++ b/util.c @@ -79,6 +79,21 @@ # define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif +int +string_to_uint(const char *str) +{ + char *error; + long value; + + if (!*str) + return -1; + errno = 0; + value = strtol(str, &error, 10); + if (errno || *error || value < 0 || (long)(int)value != value) + return -1; + return (int)value; +} + int tv_nz(struct timeval *a) {