In strace following code sentences are frequently used: var = malloc(fdsize); if (!var) die_out_of_memory();
This patch introduces xmalloc and friends which simplify above sentences like: var = xmalloc(fdsize); Here friends are xcalloc and xreallocarray. Some part of xreallocarray is derived from reallocarray which is developed at OpenBSD project as a safer alternative of realloc. * defs.h: (xmalloc, xcalloc, xreallocarray): New declarations. * xmalloc.c (xmalloc, xcalloc, xreallocarray): New file with new functions. * vsprintf.c (strace_vfprintf): Use xmalloc. * util.c (printstr): Use xmalloc. * unwind.c (unwind_tcb_init): Use xmalloc. (build_mmap_cache): Use xmalloc and xreallocarray. (get_symbol_name): Use xreallocarray. * syscall.c (reallocate_qual): Use xreallocarray. * strace.c (expand_tcbtab): Use xcalloc and xreallocarray. (init): Use xcalloc and xmalloc. * pathtrace.c (storepath): Use xreallocarray. (pathtrace_match): Use xmalloc. * dirent.c (sys_getdents): Use xmalloc. (sys_getdents64): Use xmalloc. * desc.c (decode_select): Use xmalloc. * count.c (count_syscall): Use xcalloc. (call_summary_pers): Use xcalloc. --- Makefile.am | 3 +- count.c | 11 ++------ defs.h | 9 ++++++ desc.c | 11 ++------ dirent.c | 8 ++---- pathtrace.c | 8 ++---- strace.c | 22 ++++----------- syscall.c | 4 +-- unwind.c | 26 +++++------------ util.c | 8 ++---- vsprintf.c | 4 +-- xmalloc.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 130 insertions(+), 76 deletions(-) create mode 100644 xmalloc.c diff --git a/Makefile.am b/Makefile.am index 8193c9e..b44b7a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 25921b2..1232d3d 100644 --- 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 34f1603..a52126c 100644 --- a/defs.h +++ b/defs.h @@ -434,6 +434,15 @@ void perror_msg_and_die(const char *fmt, ...) ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_NORETURN; void die_out_of_memory(void) ATTRIBUTE_NORETURN; +/* + * Memory allocator + die_out_of_memory + */ +void *xmalloc(size_t size) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1)); +void *xcalloc(size_t nmmeb, size_t size) + ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1, 2)); +void *xreallocarray(void *optr, size_t nmemb, size_t size) + ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1, 2)); + #if USE_CUSTOM_PRINTF /* * See comment in vsprintf.c for allowed formats. diff --git a/desc.c b/desc.c index 485c802..1c10d9f 100644 --- a/desc.c +++ b/desc.c @@ -338,11 +338,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) { @@ -387,9 +384,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 = ""; diff --git a/dirent.c b/dirent.c index d30e0d2..2b6acb6 100644 --- a/dirent.c +++ b/dirent.c @@ -83,9 +83,7 @@ sys_getdents(struct tcb *tcp) 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); @@ -167,9 +165,7 @@ sys_getdents64(struct tcb *tcp) 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/pathtrace.c b/pathtrace.c index 0db7fe3..b8da572 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -91,9 +91,7 @@ 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 +285,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) diff --git a/strace.c b/strace.c index 5eab360..84a1334 100644 --- a/strace.c +++ b/strace.c @@ -676,10 +676,8 @@ 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) @@ -1445,12 +1443,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++; @@ -1596,9 +1590,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 +1683,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]) { diff --git a/syscall.c b/syscall.c index d54d8b6..bfaee9f 100644 --- a/syscall.c +++ b/syscall.c @@ -381,9 +381,7 @@ 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; diff --git a/unwind.c b/unwind.c index 6f422a1..f31c619 100644 --- 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,10 +193,8 @@ 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]; @@ -291,9 +285,7 @@ get_symbol_name(unw_cursor_t *cursor, char **name, break; } *size *= 2; - *name = realloc(*name, *size); - if (!*name) - die_out_of_memory(); + *name = xreallocarray(*name, *size, 1); } } @@ -372,9 +364,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,9 +480,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, diff --git a/util.c b/util.c index 6afafbb..9dad3f1 100644 --- 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; diff --git a/vsprintf.c b/vsprintf.c index 0125e72..aae40db 100644 --- a/vsprintf.c +++ b/vsprintf.c @@ -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 index 0000000..a34223d --- /dev/null +++ b/xmalloc.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1991, 1992 Paul Kranenburg <p...@cs.few.eur.nl> + * Copyright (c) 1993 Branko Lankester <bra...@hacktic.nl> + * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <j...@world.std.com> + * Copyright (c) 1996-1999 Wichert Akkerman <wich...@cistron.nl> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defs.h" + +void * +xmalloc(size_t size) +{ + void *r = malloc(size); + if (!r) + die_out_of_memory(); + return r; +} + +void * +xcalloc(size_t nmmeb, size_t size) +{ + void *r = calloc(nmmeb, size); + if (!r) + die_out_of_memory(); + return r; +} + +/* (part of xreallocarray is derived from reallocarray) + * + * About reallocarray + * + * Copyright (c) 2008 Otto Moerbeek <o...@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +xreallocarray(void *optr, size_t nmemb, size_t size) +{ + void *r; + size_t bytes = nmemb * size; + + if (((nmemb | size) >= MUL_NO_OVERFLOW) && + size && bytes / size != nmemb) + die_out_of_memory(); + + + r = realloc(optr, size * nmemb); + if (!r) + die_out_of_memory(); + + return r; +} -- 2.1.0 ------------------------------------------------------------------------------ BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT Develop your own process in accordance with the BPMN 2 standard Learn Process modeling best practices with Bonita BPM through live exercises http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_ source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel