diff --git a/Makefile b/Makefile index 5c55f43..7ca299b 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,7 @@ LIBUTILSRC =\ libutil/fnck.c\ libutil/getlines.c\ libutil/human.c\ + libutil/mallocarray.c\ libutil/md5.c\ libutil/mode.c\ libutil/putword.c\ diff --git a/col.c b/col.c index 585d6aa..e6aa1c3 100644 --- a/col.c +++ b/col.c @@ -177,7 +177,7 @@ allocbuf(void) { char **bp; - buff = ereallocarray(buff, pagsize, sizeof(*buff)); + buff = emallocarray(pagsize, sizeof(*buff)); for (bp = buff; bp < &buff[pagsize]; ++bp) *bp = emalloc(NCOLS); } diff --git a/cut.c b/cut.c index 1658a5c..586636c 100644 --- a/cut.c +++ b/cut.c @@ -56,7 +56,7 @@ parselist(char *str) if (*s == ',') n++; } - r = ereallocarray(r, n, sizeof(*r)); + r = emallocarray(n, sizeof(*r)); for (s = str; n; n--, s++) { r->min = (*s == '-') ? 1 : strtoul(s, &s, 10); r->max = (*s == '-') ? strtoul(s + 1, &s, 10) : r->min; diff --git a/find.c b/find.c index ebea89b..91827c6 100644 --- a/find.c +++ b/find.c @@ -595,7 +595,7 @@ get_exec_arg(char *argv[], Extra *extra) e->u.p.arglen = e->u.p.filelen = 0; e->u.p.first = e->u.p.next = arg - argv - 1; e->u.p.cap = (arg - argv) * 2; - e->argv = ereallocarray(e->argv, e->u.p.cap, sizeof(*e->argv)); + e->argv = emallocarray(e->u.p.cap, sizeof(*e->argv)); for (arg = argv, new = e->argv; *arg; arg++, new++) { *new = *arg; @@ -604,7 +604,7 @@ get_exec_arg(char *argv[], Extra *extra) arg++; /* due to our extra NULL */ } else { e->argv = argv; - e->u.s.braces = ereallocarray(e->u.s.braces, ++nbraces, sizeof(*e->u.s.braces)); /* ++ for NULL */ + e->u.s.braces = emallocarray(++nbraces, sizeof(*e->u.s.braces)); /* ++ for NULL */ for (arg = argv, braces = e->u.s.braces; *arg; arg++) if (!strcmp(*arg, "{}")) @@ -632,7 +632,7 @@ get_ok_arg(char *argv[], Extra *extra) *arg = NULL; o->argv = argv; - o->braces = ereallocarray(o->braces, ++nbraces, sizeof(*o->braces)); + o->braces = emallocarray(++nbraces, sizeof(*o->braces)); for (arg = argv, braces = o->braces; *arg; arg++) if (!strcmp(*arg, "{}")) @@ -824,7 +824,7 @@ parse(int argc, char **argv) * https://en.wikipedia.org/wiki/Shunting-yard_algorithm * read from infix, resulting rpn ends up in rpn, next position in rpn is out * push operators onto stack, next position in stack is top */ - rpn = ereallocarray(rpn, ntok + gflags.print, sizeof(*rpn)); + rpn = emallocarray(ntok + gflags.print, sizeof(*rpn)); for (tok = infix, out = rpn, top = stack; tok->type != END; tok++) { switch (tok->type) { case PRIM: *out++ = *tok; break; diff --git a/libutil/mallocarray.c b/libutil/mallocarray.c new file mode 100644 index 0000000..e89dfd2 --- /dev/null +++ b/libutil/mallocarray.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * 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. + */ + +#include +#include +#include +#include + +#include "../util.h" + +/* + * 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 (1UL << (sizeof(size_t) * 4)) + +void * +mallocarray(size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return malloc(nmemb * size); +} + +void * +emallocarray(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = mallocarray(nmemb, size))) + eprintf("mallocarray: out of memory\n"); + + return p; +} diff --git a/libutil/reallocarray.c b/libutil/reallocarray.c index fb28267..c6e5219 100644 --- a/libutil/reallocarray.c +++ b/libutil/reallocarray.c @@ -1,4 +1,3 @@ -/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */ /* * Copyright (c) 2008 Otto Moerbeek * diff --git a/ls.c b/ls.c index 44d430f..0099f5b 100644 --- a/ls.c +++ b/ls.c @@ -269,7 +269,7 @@ usage(void) int main(int argc, char *argv[]) { - struct entry *ents = NULL; + struct entry *ents; size_t i; ARGBEGIN { @@ -341,7 +341,7 @@ main(int argc, char *argv[]) if (argc == 0) *--argv = ".", argc++; - ents = ereallocarray(ents, argc, sizeof(*ents)); + ents = emallocarray(argc, sizeof(*ents)); for (i = 0; i < argc; i++) mkent(&ents[i], argv[i], 1, Hflag || Lflag); diff --git a/paste.c b/paste.c index 7a3878e..99046cc 100644 --- a/paste.c +++ b/paste.c @@ -85,8 +85,8 @@ usage(void) int main(int argc, char *argv[]) { - struct fdescr *dsc = NULL; - Rune *delim = NULL; + struct fdescr *dsc; + Rune *delim; size_t i, len; int seq = 0; char *adelim = "\t"; @@ -107,11 +107,11 @@ main(int argc, char *argv[]) /* populate delimiters */ unescape(adelim); - delim = ereallocarray(delim, utflen(adelim) + 1, sizeof(*delim)); + delim = emallocarray(utflen(adelim) + 1, sizeof(*delim)); len = utftorunestr(adelim, delim); /* populate file list */ - dsc = ereallocarray(dsc, argc, sizeof(*dsc)); + dsc = emallocarray(argc, sizeof(*dsc)); for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-") == 0) diff --git a/printf.c b/printf.c index e959a46..656b808 100644 --- a/printf.c +++ b/printf.c @@ -111,7 +111,7 @@ main(int argc, char *argv[]) break; case 'c': unescape(arg); - rarg = ereallocarray(rarg, utflen(arg) + 1, sizeof(*rarg)); + rarg = emallocarray(utflen(arg) + 1, sizeof(*rarg)); utftorunestr(arg, rarg); efputrune(rarg, stdout, ""); free(rarg); @@ -125,7 +125,7 @@ main(int argc, char *argv[]) if (arg[j] == '\'' || arg[j] == '\"') { arg += j + 1; unescape(arg); - rarg = ereallocarray(rarg, utflen(arg) + 1, sizeof(*rarg)); + rarg = emallocarray(utflen(arg) + 1, sizeof(*rarg)); utftorunestr(arg, rarg); num = rarg[0]; } else diff --git a/sed.c b/sed.c index 8e98062..d413c71 100644 --- a/sed.c +++ b/sed.c @@ -596,10 +596,9 @@ chompr(char *s, Rune rune) Rune * strtorunes(char *s, size_t nrunes) { - Rune *rs = NULL, *rp; + Rune *rs, *rp; - rs = ereallocarray(rs, nrunes + 1, sizeof(*rs)); - rp = rs; + rp = rs = emallocarray(nrunes + 1, sizeof(*rs)); while (nrunes--) s += chartorune(rp++, s); diff --git a/strings.c b/strings.c index 8b16069..b1872eb 100644 --- a/strings.c +++ b/strings.c @@ -11,11 +11,11 @@ static char *format = ""; static void strings(FILE *fp, const char *fname, size_t len) { - Rune r, *rbuf = NULL; + Rune r, *rbuf; size_t i, bread; off_t off; - rbuf = ereallocarray(rbuf, len, sizeof(*rbuf)); + rbuf = emallocarray(len, sizeof(*rbuf)); for (off = 0, i = 0; (bread = efgetrune(&r, fp, fname)); ) { off += bread; diff --git a/tr.c b/tr.c index 52b223f..039df36 100644 --- a/tr.c +++ b/tr.c @@ -71,16 +71,16 @@ rstrmatch(Rune *r, char *s, size_t n) static size_t makeset(char *str, struct range **set, int (**check)(Rune)) { - Rune *rstr = NULL; + Rune *rstr; size_t len, i, j, m, n; size_t q, setranges = 0; int factor, base; /* rstr defines at most len ranges */ unescape(str); - rstr = ereallocarray(rstr, utflen(str) + 1, sizeof(*rstr)); + rstr = emallocarray(utflen(str) + 1, sizeof(*rstr)); len = utftorunestr(str, rstr); - *set = ereallocarray(*set, len, sizeof(**set)); + *set = emallocarray(len, sizeof(**set)); for (i = 0; i < len; i++) { if (rstr[i] == '[') { diff --git a/util.h b/util.h index 7370272..c4e7585 100644 --- a/util.h +++ b/util.h @@ -25,6 +25,8 @@ void apathmax(char **, size_t *); void *ecalloc(size_t, size_t); void *emalloc(size_t); +void *mallocarray(size_t, size_t); +void *emallocarray(size_t, size_t); void *erealloc(void *, size_t); void *reallocarray(void *, size_t, size_t); void *ereallocarray(void *, size_t, size_t);