]> granicus.if.org Git - strace/commitdiff
Robustify parsing of numbers from strings
authorDmitry V. Levin <ldv@altlinux.org>
Sun, 25 Mar 2012 21:49:48 +0000 (21:49 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sun, 25 Mar 2012 21:49:48 +0000 (21:49 +0000)
* 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.

defs.h
strace.c
syscall.c
util.c

diff --git a/defs.h b/defs.h
index e46e230a544f7f597fabeeb194358b62b3dc3ba4..334840030fbefb18a26ad50b539095c9c9261713 100644 (file)
--- 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
index ac7e67203878153ca86a42d01e18c40b69cc4c4b..c211ac73ad1a2ea18cd84cdc1af7b09dbca93732 100644 (file)
--- 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);
index c4ac9778e08d93e484972284550660fedc159326..cf9cd0820754e3885f2a826f662cbcae13c8c029 100644 (file)
--- 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 e57f46ae3045b0aa8b5ca525e11b0025518a8c5d..ea3488d4afa3dbdd1cb0ab35e3340378349727c0 100644 (file)
--- a/util.c
+++ b/util.c
 # 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)
 {