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 e46e230..3348400 100644
--- a/defs.h
+++ b/defs.h
@@ -489,6 +489,8 @@
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 ac7e672..c211ac7 100644
--- a/strace.c
+++ b/strace.c
@@ -131,7 +131,7 @@
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 @@
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 @@
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 @@
if (de->d_fileno == 0)
continue;
+ /* we trust /proc filesystem */
tid = atoi(de->d_name);
if (tid <= 0)
continue;
@@ -1445,7 +1452,7 @@
init(int argc, char *argv[])
{
struct tcb *tcp;
- int c;
+ int c, i;
int optF = 0;
struct sigaction sa;
@@ -1547,9 +1554,9 @@
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 @@
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 @@
}
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 @@
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 c4ac977..cf9cd08 100644
--- a/syscall.c
+++ b/syscall.c
@@ -338,7 +338,7 @@
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 @@
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 @@
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 e57f46a..ea3488d 100644
--- a/util.c
+++ b/util.c
@@ -80,6 +80,21 @@
#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)
{
return a->tv_sec || a->tv_usec;