]> granicus.if.org Git - strace/commitdiff
Make out-of-memory handling more uniform
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 31 Aug 2011 12:00:02 +0000 (14:00 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 31 Aug 2011 12:00:02 +0000 (14:00 +0200)
This fixes one real bug in dumpstr().

* defs.h: Declare die_out_of_memory().
* strace.c (die_out_of_memory): New function.
(strace_popen): If allocation fails, call die_out_of_memory().
(main): Likewise.
(expand_tcbtab): Likewise.
(rebuild_pollv): Likewise.
* count.c (count_syscall): Likewise.
(call_summary_pers): Likewise.
* desc.c (decode_select): Likewise.
* file.c (sys_getdents): Likewise.
(sys_getdents64): Likewise.
(sys_getdirentries): Likewise.
* pathtrace.c (pathtrace_match): Likewise.
* syscall.c (qualify): Likewise.
* util.c (printstr): Likewise.
(dumpiov): Likewise.
(dumpstr): Likewise.
(fixvfork): Likewise.
* mem.c (sys_mincore): Don't check free() parameter for NULL.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
count.c
defs.h
desc.c
file.c
mem.c
pathtrace.c
strace.c
syscall.c
util.c

diff --git a/count.c b/count.c
index 77fc919d6f44ff2eec586ab454050999cc03c24b..1785242ac335cfc995f0836a7bd229f640643d30 100644 (file)
--- a/count.c
+++ b/count.c
@@ -55,11 +55,8 @@ count_syscall(struct tcb *tcp, struct timeval *tv)
 
        if (!counts) {
                counts = calloc(nsyscalls, sizeof(*counts));
-               if (!counts) {
-                       fprintf(stderr,
-                               "strace: out of memory for call counts\n");
-                       exit(1);
-               }
+               if (!counts)
+                       die_out_of_memory();
        }
 
        counts[tcp->scno].calls++;
@@ -157,10 +154,8 @@ call_summary_pers(FILE *outf)
        char    error_str[16];
        int    *sorted_count = calloc(sizeof(int), nsyscalls);
 
-       if (!sorted_count) {
-               fprintf(stderr, "strace: out of memory for call summary\n");
-               return;
-       }
+       if (!sorted_count)
+               die_out_of_memory();
 
        call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
        if (overhead.tv_sec == -1) {
diff --git a/defs.h b/defs.h
index dfca2c12ed90a275626f93e5a22df8385000f804..bb2e395d5c17eae45924eb194eb27c9ebd12c7ee 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -580,6 +580,7 @@ void error_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
 void perror_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
 void error_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
 void perror_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
+void die_out_of_memory(void) __attribute__ ((noreturn));
 
 extern void set_personality(int personality);
 extern const char *xlookup(const struct xlat *, int);
diff --git a/desc.c b/desc.c
index a8dbe9551c0df6cf2ab7c92a3d75e08e8dc58d9f..e77a2387d779a93ac007bf08a02af4a3a10f4540 100644 (file)
--- a/desc.c
+++ b/desc.c
@@ -497,9 +497,9 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
        long arg;
 
        if (entering(tcp)) {
-               fds = (fd_set *) malloc(fdsize);
-               if (fds == NULL)
-                       fprintf(stderr, "out of memory\n");
+               fds = malloc(fdsize);
+               if (!fds)
+                       die_out_of_memory();
                nfds = args[0];
                tprintf("%d", nfds);
                for (i = 0; i < 3; i++) {
@@ -508,7 +508,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
                                tprintf(", NULL");
                                continue;
                        }
-                       if (fds == NULL || !verbose(tcp)) {
+                       if (!verbose(tcp)) {
                                tprintf(", %#lx", arg);
                                continue;
                        }
@@ -546,8 +546,8 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
                }
 
                fds = malloc(fdsize);
-               if (fds == NULL)
-                       fprintf(stderr, "out of memory\n");
+               if (!fds)
+                       die_out_of_memory();
 
                tcp->auxstr = outstr;
                outptr = outstr;
@@ -556,8 +556,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
                        int first = 1;
 
                        arg = args[i+1];
-                       if (fds == NULL || !arg ||
-                           umoven(tcp, arg, fdsize, (char *) fds) < 0)
+                       if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
                                continue;
                        for (j = 0; j < args[0]; j++) {
                                if (FD_ISSET(j, fds)) {
diff --git a/file.c b/file.c
index c40fde2b7b8b41c9aebccaad6f45c54491420e2a..09977e9c434a092cf3125aea764a0befea02e80f 100644 (file)
--- a/file.c
+++ b/file.c
@@ -2422,11 +2422,8 @@ sys_getdents(struct tcb *tcp)
        }
        len = tcp->u_rval;
        buf = len ? malloc(len) : NULL;
-       if (len && !buf) {
-               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
-               fprintf(stderr, "out of memory\n");
-               return 0;
-       }
+       if (len && !buf)
+               die_out_of_memory();
        if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
                tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
                free(buf);
@@ -2507,11 +2504,8 @@ sys_getdents64(struct tcb *tcp)
        }
        len = tcp->u_rval;
        buf = len ? malloc(len) : NULL;
-       if (len && !buf) {
-               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
-               fprintf(stderr, "out of memory\n");
-               return 0;
-       }
+       if (len && !buf)
+               die_out_of_memory();
        if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
                tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
                free(buf);
@@ -2581,11 +2575,8 @@ sys_getdirentries(struct tcb *tcp)
        }
        len = tcp->u_rval;
        buf = malloc(len);
-       if (buf == NULL) {
-               tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
-               fprintf(stderr, "out of memory\n");
-               return 0;
-       }
+       if (!buf)
+               die_out_of_memory();
        if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
                tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
                free(buf);
diff --git a/mem.c b/mem.c
index 763bea162e85ebbb59fa951515f2cc8cad7e871b..43b422f59f17c1485d3ea8086bae5bb4e0fb547e 100644 (file)
--- a/mem.c
+++ b/mem.c
@@ -564,12 +564,12 @@ sys_mctl(struct tcb *tcp)
 int
 sys_mincore(struct tcb *tcp)
 {
-       unsigned long i, len;
-       char *vec = NULL;
-
        if (entering(tcp)) {
                tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
        } else {
+               unsigned long i, len;
+               char *vec = NULL;
+
                len = tcp->u_arg[1];
                if (syserror(tcp) || tcp->u_arg[2] == 0 ||
                        (vec = malloc(len)) == NULL ||
@@ -586,8 +586,7 @@ sys_mincore(struct tcb *tcp)
                        }
                        tprintf("]");
                }
-               if (vec)
-                       free(vec);
+               free(vec);
        }
        return 0;
 }
index 3ebb427eca319f646e5b8ba160cc516bfa1bb536..23ab47ee48b0a91fb7f33e4c78f406a830c4cc68 100644 (file)
@@ -290,10 +290,8 @@ pathtrace_match(struct tcb *tcp)
                          & -sizeof(long));
                fds = malloc(fdsize);
 
-               if (fds == NULL) {
-                       fprintf(stderr, "out of memory\n");
-                       return 0;
-               }
+               if (!fds)
+                       die_out_of_memory();
 
                for (i = 1; i <= 3; ++i) {
                        if (args[i] == 0)
index bb41ce2b01bffa6785b270894b7fafdb80cfbbce..83ebc5b0d51d28812d2ba56d8c7ac51833a0e53f 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -264,6 +264,15 @@ void perror_msg_and_die(const char *fmt, ...)
        die();
 }
 
+void die_out_of_memory(void)
+{
+       static bool recursed = 0;
+       if (recursed)
+               exit(1);
+       recursed = 1;
+       error_msg_and_die("Out of memory");
+}
+
 #ifdef SVR4
 #ifdef MIPS
 void
@@ -383,7 +392,7 @@ strace_popen(const char *command)
        swap_uid();
        fp = fdopen(fds[1], "w");
        if (!fp)
-               error_msg_and_die("Out of memory");
+               die_out_of_memory();
        return fp;
 }
 
@@ -947,11 +956,11 @@ main(int argc, char *argv[])
        /* Allocate the initial tcbtab.  */
        tcbtabsize = argc;      /* Surely enough for all -p args.  */
        tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
-       if (tcbtab == NULL)
-               error_msg_and_die("Out of memory");
+       if (!tcbtab)
+               die_out_of_memory();
        tcp = calloc(tcbtabsize, sizeof(*tcp));
-       if (tcp == NULL)
-               error_msg_and_die("Out of memory");
+       if (!tcp)
+               die_out_of_memory();
        for (c = 0; c < tcbtabsize; c++)
                tcbtab[c] = tcp++;
 
@@ -1078,9 +1087,8 @@ main(int argc, char *argv[])
                        username = strdup(optarg);
                        break;
                case 'E':
-                       if (putenv(optarg) < 0) {
-                               error_msg_and_die("Out of memory");
-                       }
+                       if (putenv(optarg) < 0)
+                               die_out_of_memory();
                        break;
                default:
                        usage(stderr, 1);
@@ -1090,7 +1098,7 @@ main(int argc, char *argv[])
 
        acolumn_spaces = malloc(acolumn + 1);
        if (!acolumn_spaces)
-               error_msg_and_die("Out of memory");
+               die_out_of_memory();
        memset(acolumn_spaces, ' ', acolumn);
        acolumn_spaces[acolumn] = '\0';
 
@@ -1240,8 +1248,8 @@ expand_tcbtab(void)
        int i = tcbtabsize;
        struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
        struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
-       if (newtab == NULL || newtcbs == NULL)
-               error_msg_and_die("Out of memory");
+       if (!newtab || !newtcbs)
+               die_out_of_memory();
        tcbtabsize *= 2;
        tcbtab = newtab;
        while (i < tcbtabsize)
@@ -1866,9 +1874,8 @@ rebuild_pollv(void)
 
        free(pollv);
        pollv = malloc(nprocs * sizeof(pollv[0]));
-       if (pollv == NULL) {
-               error_msg_and_die("Out of memory");
-       }
+       if (!pollv)
+               die_out_of_memory();
 
        for (i = j = 0; i < tcbtabsize; i++) {
                struct tcb *tcp = tcbtab[i];
index f8c4c8bafcc4ded474104d7d293b96bcfb21bc45..b21ce01925f22145fcdc0a1bd1727d10d3627997 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -473,10 +473,8 @@ qualify(const char *s)
                qualify_one(i, opt->bitflag, !not, -1);
        }
        copy = strdup(s);
-       if (!copy) {
-               fprintf(stderr, "out of memory\n");
-               exit(1);
-       }
+       if (!copy)
+               die_out_of_memory();
        for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
                if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
                        for (i = 0; i < nsyscalls0; i++)
diff --git a/util.c b/util.c
index 7bf2698404f3e6d87bb16fa302c8fb3a9d635356..75a449dc8c78406039ae24d2ee9b213d1326c791 100644 (file)
--- a/util.c
+++ b/util.c
@@ -619,14 +619,15 @@ printstr(struct tcb *tcp, long addr, int len)
                return;
        }
        /* Allocate static buffers if they are not allocated yet. */
-       if (!str)
+       if (!str) {
                str = malloc(max_strlen + 1);
-       if (!outstr)
+               if (!str)
+                       die_out_of_memory();
+       }
+       if (!outstr) {
                outstr = malloc(4 * max_strlen + sizeof "\"...\"");
-       if (!str || !outstr) {
-               fprintf(stderr, "out of memory\n");
-               tprintf("%#lx", addr);
-               return;
+               if (!outstr)
+                       die_out_of_memory();
        }
 
        if (len < 0) {
@@ -687,10 +688,9 @@ dumpiov(struct tcb *tcp, int len, long addr)
        unsigned long size;
 
        size = sizeof_iov * (unsigned long) len;
-       if (size / sizeof_iov != len
+       if (size / sizeof_iov != len /* overflow? */
            || (iov = malloc(size)) == NULL) {
-               fprintf(stderr, "out of memory\n");
-               return;
+               die_out_of_memory();
        }
        if (umoven(tcp, addr, size, (char *) iov) >= 0) {
                for (i = 0; i < len; i++) {
@@ -715,18 +715,14 @@ dumpstr(struct tcb *tcp, long addr, int len)
 {
        static int strsize = -1;
        static unsigned char *str;
-       static char outstr[80];
        char *s;
        int i, j;
 
        if (strsize < len) {
                free(str);
                str = malloc(len);
-               if (str == NULL) {
-                       fprintf(stderr, "out of memory\n");
-       /* BUG! On next call we may use NULL str! */
-                       return;
-               }
+               if (!str)
+                       die_out_of_memory();
                strsize = len;
        }
 
@@ -734,6 +730,8 @@ dumpstr(struct tcb *tcp, long addr, int len)
                return;
 
        for (i = 0; i < len; i += 16) {
+               char outstr[80];
+
                s = outstr;
                sprintf(s, " | %05x ", i);
                s += 9;
@@ -1741,10 +1739,8 @@ fixvfork(struct tcb *tcp)
                return -1;
        }
        strtab = malloc((unsigned)ld.ld_symb_size);
-       if (strtab == NULL) {
-               fprintf(stderr, "out of memory\n");
-               return -1;
-       }
+       if (!strtab)
+               die_out_of_memory();
        if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
                                        (int)ld.ld_symb_size, strtab) < 0)
                goto err;