]> granicus.if.org Git - strace/commitdiff
Introduce memory allocation wrappers
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 25 May 2015 20:41:02 +0000 (20:41 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 25 May 2015 22:25:22 +0000 (22:25 +0000)
Introduce wrappers to the following functions that do memory allocation:
malloc, calloc, realloc, strdup.

This commit is a follow-up to the related discussions in strace-devel ML:
http://sourceforge.net/p/strace/mailman/message/33618180/
http://sourceforge.net/p/strace/mailman/message/33733470/

* defs.h (xmalloc, xcalloc, xreallocarray, xstrdup): New prototypes.
* xmalloc.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* count.c (count_syscall, call_summary_pers): Use xcalloc.
* desc.c (decode_select): Use xmalloc.
* dirent.c (sys_getdents, sys_getdents64): Likewise.
* net.c (sys_recvmmsg): Use xstrdup.
* pathtrace.c (storepath): Use xreallocarray.
(pathtrace_match): Use xmalloc.
* strace.c (die_out_of_memory): Move to xmalloc.c.
(expand_tcbtab): Use xcalloc and xreallocarray.
(startup_child): Use xstrdup.
(init): Use xmalloc, xcalloc, and xstrdup.
* syscall.c (reallocate_qual): Use xreallocarray.
(qualify): Use xstrdup.
* unwind.c (unwind_tcb_init): Use xmalloc.
(build_mmap_cache): Use xcalloc, xreallocarray, and xstrdup.
(get_symbol_name): Use xreallocarray.
(stacktrace_walk, queue_put): Use xmalloc.
* util.c (printstr): Use xmalloc.
* vsprintf.c (strace_vfprintf): Likewise.

13 files changed:
Makefile.am
count.c
defs.h
desc.c
dirent.c
net.c
pathtrace.c
strace.c
syscall.c
unwind.c
util.c
vsprintf.c
xmalloc.c [new file with mode: 0644]

index d4be76f6dcba63df0905b0937494dc9d1b0873d5..e2a0f747f1dc970b7a7f8327042143ff2859747a 100644 (file)
@@ -123,7 +123,8 @@ strace_SOURCES =    \
        v4l2.c          \
        vsprintf.c      \
        wait.c          \
-       xattr.c
+       xattr.c         \
+       xmalloc.c
 
 if USE_LIBUNWIND
 strace_SOURCES += unwind.c
diff --git a/count.c b/count.c
index 25921b25713b1d553f0f08e91a68246a576176ab..1232d3dbf0dc712a2eccf3460ad9dd38ef839e98 100644 (file)
--- a/count.c
+++ b/count.c
@@ -58,11 +58,8 @@ count_syscall(struct tcb *tcp, const struct timeval *syscall_exiting_tv)
        if (!SCNO_IN_RANGE(scno))
                return;
 
-       if (!counts) {
-               counts = calloc(nsyscalls, sizeof(*counts));
-               if (!counts)
-                       die_out_of_memory();
-       }
+       if (!counts)
+               counts = xcalloc(nsyscalls, sizeof(*counts));
        cc = &counts[scno];
 
        cc->calls++;
@@ -171,9 +168,7 @@ call_summary_pers(FILE *outf)
        fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
                dashes, dashes, dashes, dashes, dashes, dashes);
 
-       sorted_count = calloc(sizeof(int), nsyscalls);
-       if (!sorted_count)
-               die_out_of_memory();
+       sorted_count = xcalloc(sizeof(int), nsyscalls);
        call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
        if (overhead.tv_sec == -1) {
                tv_mul(&overhead, &shortest, 8);
diff --git a/defs.h b/defs.h
index 77c819c62a5997b59737525e45e7449bea5f2b16..c02f8103945513c3b318a2dcd7b5fb8f856cb94b 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -434,6 +434,13 @@ void perror_msg_and_die(const char *fmt, ...)
        ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_NORETURN;
 void die_out_of_memory(void) ATTRIBUTE_NORETURN;
 
+void *xmalloc(size_t size) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1));
+void *xcalloc(size_t nmemb, size_t size)
+       ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1, 2));
+void *xreallocarray(void *ptr, size_t nmemb, size_t size)
+       ATTRIBUTE_ALLOC_SIZE((2, 3));
+char *xstrdup(const char *str) ATTRIBUTE_MALLOC;
+
 #if USE_CUSTOM_PRINTF
 /*
  * See comment in vsprintf.c for allowed formats.
diff --git a/desc.c b/desc.c
index 1b9dd1a5fb9a7c50d24321aaf0c27844b1735d18..e1d01dc4e9d822a1c810a73f7f1e6471849fd5fb 100644 (file)
--- a/desc.c
+++ b/desc.c
@@ -331,11 +331,8 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
        if (entering(tcp)) {
                tprintf("%d", (int) args[0]);
 
-               if (verbose(tcp) && fdsize > 0) {
-                       fds = malloc(fdsize);
-                       if (!fds)
-                               die_out_of_memory();
-               }
+               if (verbose(tcp) && fdsize > 0)
+                       fds = xmalloc(fdsize);
                for (i = 0; i < 3; i++) {
                        arg = args[i+1];
                        if (arg == 0) {
@@ -380,9 +377,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
                        return RVAL_STR;
                }
 
-               fds = malloc(fdsize);
-               if (!fds)
-                       die_out_of_memory();
+               fds = xmalloc(fdsize);
 
                outptr = outstr;
                sep = "";
index 32f04b9e965ac748583ee0b4090f0f888e996ab4..988d535c02381d8171440ebfc3c5a95b5c333cf8 100644 (file)
--- a/dirent.c
+++ b/dirent.c
@@ -81,9 +81,7 @@ SYS_FUNC(getdents)
                len = tcp->u_rval;
 
        if (len) {
-               buf = malloc(len);
-               if (!buf)
-                       die_out_of_memory();
+               buf = xmalloc(len);
                if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
                        tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
                        free(buf);
@@ -164,9 +162,7 @@ SYS_FUNC(getdents64)
                len = tcp->u_rval;
 
        if (len) {
-               buf = malloc(len);
-               if (!buf)
-                       die_out_of_memory();
+               buf = xmalloc(len);
                if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
                        tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
                        free(buf);
diff --git a/net.c b/net.c
index 2ed950de316eec5a2506260862b48b67ce209d39..0a3c601fb0c9f68f28a8be5bf67adff3f0fd260a 100644 (file)
--- a/net.c
+++ b/net.c
@@ -995,7 +995,7 @@ SYS_FUNC(recvmmsg)
                        /* Abusing tcp->auxstr as temp storage.
                         * Will be used and freed on syscall exit.
                         */
-                       tcp->auxstr = strdup(str);
+                       tcp->auxstr = xstrdup(str);
                } else {
                        tprintf("%#lx, %ld, ", tcp->u_arg[1], tcp->u_arg[2]);
                        printflags(msg_flags, tcp->u_arg[3], "MSG_???");
index 0db7fe31d9a31e9e666223bbaecbf2faadfc9530..894dd5c963eb30c8162c956c40e3add1f0fad01e 100644 (file)
@@ -91,9 +91,8 @@ storepath(const char *path)
                return; /* already in table */
 
        i = num_selected++;
-       paths_selected = realloc(paths_selected, num_selected * sizeof(paths_selected[0]));
-       if (!paths_selected)
-               die_out_of_memory();
+       paths_selected = xreallocarray(paths_selected, num_selected,
+                                      sizeof(paths_selected[0]));
        paths_selected[i] = path;
 }
 
@@ -287,9 +286,7 @@ pathtrace_match(struct tcb *tcp)
                if (nfds > 1024*1024)
                        nfds = 1024*1024;
                fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
-               fds = malloc(fdsize);
-               if (!fds)
-                       die_out_of_memory();
+               fds = xmalloc(fdsize);
 
                for (i = 1; i <= 3; ++i) {
                        if (args[i] == 0)
index 5eab360313000a5daecb896f79b3312e24230760..0bffd5e1832d934efe1f5118a750de49f1e6e0e1 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -324,15 +324,6 @@ 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");
-}
-
 static void
 error_opt_arg(int opt, const char *arg)
 {
@@ -676,10 +667,9 @@ expand_tcbtab(void)
           So tcbtab is a table of pointers.  Since we never
           free the TCBs, we allocate a single chunk of many.  */
        unsigned int i = tcbtabsize;
-       struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
-       struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
-       if (!newtab || !newtcbs)
-               die_out_of_memory();
+       struct tcb *newtcbs = xcalloc(tcbtabsize, sizeof(newtcbs[0]));
+       struct tcb **newtab = xreallocarray(tcbtab, tcbtabsize * 2,
+                                           sizeof(tcbtab[0]));
        tcbtabsize *= 2;
        tcbtab = newtab;
        while (i < tcbtabsize)
@@ -1233,7 +1223,7 @@ startup_child(char **argv)
         * On NOMMU, can be safely freed only after execve in tracee.
         * It's hard to know when that happens, so we just leak it.
         */
-       params_for_tracee.pathname = NOMMU_SYSTEM ? strdup(pathname) : pathname;
+       params_for_tracee.pathname = NOMMU_SYSTEM ? xstrdup(pathname) : pathname;
 
 #if defined HAVE_PRCTL && defined PR_SET_PTRACER && defined PR_SET_PTRACER_ANY
        if (daemonized_tracer)
@@ -1445,12 +1435,8 @@ init(int argc, char *argv[])
 
        /* Allocate the initial tcbtab.  */
        tcbtabsize = argc;      /* Surely enough for all -p args.  */
-       tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
-       if (!tcbtab)
-               die_out_of_memory();
-       tcp = calloc(tcbtabsize, sizeof(*tcp));
-       if (!tcp)
-               die_out_of_memory();
+       tcbtab = xcalloc(tcbtabsize, sizeof(tcbtab[0]));
+       tcp = xcalloc(tcbtabsize, sizeof(*tcp));
        for (tcbi = 0; tcbi < tcbtabsize; tcbi++)
                tcbtab[tcbi] = tcp++;
 
@@ -1548,7 +1534,7 @@ init(int argc, char *argv[])
                        qualify(optarg);
                        break;
                case 'o':
-                       outfname = strdup(optarg);
+                       outfname = xstrdup(optarg);
                        break;
                case 'O':
                        i = string_to_uint(optarg);
@@ -1572,7 +1558,7 @@ init(int argc, char *argv[])
                        set_sortby(optarg);
                        break;
                case 'u':
-                       username = strdup(optarg);
+                       username = xstrdup(optarg);
                        break;
 #ifdef USE_LIBUNWIND
                case 'k':
@@ -1596,9 +1582,7 @@ init(int argc, char *argv[])
        argv += optind;
        /* argc -= optind; - no need, argc is not used below */
 
-       acolumn_spaces = malloc(acolumn + 1);
-       if (!acolumn_spaces)
-               die_out_of_memory();
+       acolumn_spaces = xmalloc(acolumn + 1);
        memset(acolumn_spaces, ' ', acolumn);
        acolumn_spaces[acolumn] = '\0';
 
@@ -1691,9 +1675,7 @@ init(int argc, char *argv[])
        }
 
        if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
-               char *buf = malloc(BUFSIZ);
-               if (!buf)
-                       die_out_of_memory();
+               char *buf = xmalloc(BUFSIZ);
                setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
        }
        if (outfname && argv[0]) {
index b63a5280ffc6c5db3cc209cdc0a98e81d7f3ac4b..1a9c5fc297fc104773a6d1c3054f555e66d2e681 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -381,9 +381,8 @@ reallocate_qual(const unsigned int n)
        unsigned p;
        qualbits_t *qp;
        for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
-               qp = qual_vec[p] = realloc(qual_vec[p], n * sizeof(qualbits_t));
-               if (!qp)
-                       die_out_of_memory();
+               qp = qual_vec[p] = xreallocarray(qual_vec[p], n,
+                                                sizeof(qualbits_t));
                memset(&qp[num_quals], 0, (n - num_quals) * sizeof(qualbits_t));
        }
        num_quals = n;
@@ -531,9 +530,7 @@ qualify(const char *s)
        for (i = 0; i < num_quals; i++) {
                qualify_one(i, opt->bitflag, !not, -1);
        }
-       copy = strdup(s);
-       if (!copy)
-               die_out_of_memory();
+       copy = xstrdup(s);
        for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
                int n;
                if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
index 6f422a1cf937dfc52cb44d312752605c2fd6d08a..7c091f1b982b317b5e0dba04d5b8c613ec964f83 100644 (file)
--- a/unwind.c
+++ b/unwind.c
@@ -107,9 +107,7 @@ unwind_tcb_init(struct tcb *tcp)
        if (!tcp->libunwind_ui)
                die_out_of_memory();
 
-       tcp->queue = malloc(sizeof(*tcp->queue));
-       if (!tcp->queue)
-               die_out_of_memory();
+       tcp->queue = xmalloc(sizeof(*tcp->queue));
        tcp->queue->head = NULL;
        tcp->queue->tail = NULL;
 }
@@ -152,9 +150,7 @@ build_mmap_cache(struct tcb* tcp)
                return;
        }
 
-       cache_head = calloc(cur_array_size, sizeof(*cache_head));
-       if (!cache_head)
-               die_out_of_memory();
+       cache_head = xcalloc(cur_array_size, sizeof(*cache_head));
 
        while (fgets(buffer, sizeof(buffer), fp) != NULL) {
                struct mmap_cache_t *entry;
@@ -197,19 +193,15 @@ build_mmap_cache(struct tcb* tcp)
 
                if (tcp->mmap_cache_size >= cur_array_size) {
                        cur_array_size *= 2;
-                       cache_head = realloc(cache_head,
-                                            cur_array_size * sizeof(*cache_head));
-                       if (!cache_head)
-                               die_out_of_memory();
+                       cache_head = xreallocarray(cache_head, cur_array_size,
+                                                  sizeof(*cache_head));
                }
 
                entry = &cache_head[tcp->mmap_cache_size];
                entry->start_addr = start_addr;
                entry->end_addr = end_addr;
                entry->mmap_offset = mmap_offset;
-               entry->binary_filename = strdup(binary_path);
-               if (!entry->binary_filename)
-                       die_out_of_memory();
+               entry->binary_filename = xstrdup(binary_path);
                tcp->mmap_cache_size++;
        }
        fclose(fp);
@@ -290,10 +282,8 @@ get_symbol_name(unw_cursor_t *cursor, char **name,
                        *offset = 0;
                        break;
                }
+               *name = xreallocarray(*name, 2, *size);
                *size *= 2;
-               *name = realloc(*name, *size);
-               if (!*name)
-                       die_out_of_memory();
        }
 }
 
@@ -372,9 +362,7 @@ stacktrace_walk(struct tcb *tcp,
        if (tcp->mmap_cache_size == 0)
                error_msg_and_die("bug: mmap_cache is empty");
 
-       symbol_name = malloc(symbol_name_size);
-       if (!symbol_name)
-               die_out_of_memory();
+       symbol_name = xmalloc(symbol_name_size);
 
        if (unw_init_remote(&cursor, libunwind_as, tcp->libunwind_ui) < 0)
                perror_msg_and_die("Can't initiate libunwind");
@@ -490,10 +478,7 @@ queue_put(struct queue_t *queue,
 {
        struct call_t *call;
 
-       call = malloc(sizeof(*call));
-       if (!call)
-               die_out_of_memory();
-
+       call = xmalloc(sizeof(*call));
        call->output_line = sprint_call_or_error(binary_filename,
                                                 symbol_name,
                                                 function_offset,
diff --git a/util.c b/util.c
index 6afafbbf6d74aac60c713e5f910db0797a2c81a8..9dad3f1a6789daa1092e8092c5376c040325a7d6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -763,12 +763,8 @@ printstr(struct tcb *tcp, long addr, long len)
 
                if (outstr_size / 4 != max_strlen)
                        die_out_of_memory();
-               str = malloc(max_strlen + 1);
-               if (!str)
-                       die_out_of_memory();
-               outstr = malloc(outstr_size);
-               if (!outstr)
-                       die_out_of_memory();
+               str = xmalloc(max_strlen + 1);
+               outstr = xmalloc(outstr_size);
        }
 
        size = max_strlen;
index 0125e7205a3199f70bd5e3946da6618847e38f12..aae40db30d6a58c30e2dd9fe5fd2d792e87eccaf 100644 (file)
@@ -776,9 +776,7 @@ int strace_vfprintf(FILE *fp, const char *fmt, va_list args)
        if (len >= buflen) {
                buflen = len + 256;
                free(buf);
-               buf = malloc(buflen);
-               if (!buf)
-                       die_out_of_memory();
+               buf = xmalloc(buflen);
                /*len =*/ kernel_vsnprintf(buf, buflen, fmt, args);
        }
 
diff --git a/xmalloc.c b/xmalloc.c
new file mode 100644 (file)
index 0000000..c852f55
--- /dev/null
+++ b/xmalloc.c
@@ -0,0 +1,60 @@
+#include "defs.h"
+
+void die_out_of_memory(void)
+{
+       static bool recursed = false;
+
+       if (recursed)
+               exit(1);
+       recursed = 1;
+
+       error_msg_and_die("Out of memory");
+}
+
+void *xmalloc(size_t size)
+{
+       void *p = malloc(size);
+
+       if (!p)
+               die_out_of_memory();
+
+       return p;
+}
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+       void *p = calloc(nmemb, size);
+
+       if (!p)
+               die_out_of_memory();
+
+       return p;
+}
+
+#define HALF_SIZE_T    (((size_t) 1) << (sizeof(size_t) * 4))
+
+void *xreallocarray(void *ptr, size_t nmemb, size_t size)
+{
+       size_t bytes = nmemb * size;
+
+       if ((nmemb | size) >= HALF_SIZE_T &&
+           size && bytes / size != nmemb)
+               die_out_of_memory();
+
+       void *p = realloc(ptr, bytes);
+
+       if (!p)
+               die_out_of_memory();
+
+       return p;
+}
+
+char *xstrdup(const char *str)
+{
+       char *p = strdup(str);
+
+       if (!p)
+               die_out_of_memory();
+
+       return p;
+}