[hackers] [sbase] Implement mallocarray() || FRIGN

From: <git_AT_suckless.org>
Date: Wed, 11 Mar 2015 13:42:33 +0100 (CET)

commit 71c03dc192fb8634e347c7da870c427cad350574
Author: FRIGN <dev_AT_frign.de>
Date: Tue Mar 10 22:19:19 2015 +0100

    Implement mallocarray()
    
    A function used only in the OpenBSD-Kernel as of now, but it surely
    provides a helpful interface when you just don't want to make sure
    the incoming pointer to erealloc() is really NULL so it behaves
    like malloc, making it a bit more safer.
    
    Talking about *allocarray(): It's definitely a major step in code-
    hardening. Especially as a system administrator, you should be
    able to trust your core tools without having to worry about segfaults
    like this, which can easily lead to privilege escalation.
    
    How do the GNU coreutils handle this?
    $ strings -n 4611686018427387903
    strings: invalid minimum string length -1
    $ strings -n 4611686018427387904
    strings: invalid minimum string length 0
    
    They silently overflow...
    
    In comparison, sbase:
    
    $ strings -n 4611686018427387903
    mallocarray: out of memory
    $ strings -n 4611686018427387904
    mallocarray: out of memory
    
    The first out of memory is actually a true OOM returned by malloc,
    whereas the second one is a detected overflow, which is not marked
    in a special way.
    Now tell me which diagnostic error-messages are easier to understand.

diff --git a/Makefile b/Makefile
index 5c55f43..7ca299b 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -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
_AT_@ -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
_AT_@ -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
_AT_@ -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;
_AT_@ -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, "{}"))
_AT_@ -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, "{}"))
_AT_@ -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
_AT_@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto_AT_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.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#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
_AT_@ -1,4 +1,3 @@
-/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
 /*
  * Copyright (c) 2008 Otto Moerbeek <otto_AT_drijf.net>
  *
diff --git a/ls.c b/ls.c
index 44d430f..0099f5b 100644
--- a/ls.c
+++ b/ls.c
_AT_@ -269,7 +269,7 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
- struct entry *ents = NULL;
+ struct entry *ents;
         size_t i;
 
         ARGBEGIN {
_AT_@ -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
_AT_@ -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";
_AT_@ -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
_AT_@ -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, "<stdout>");
                         free(rarg);
_AT_@ -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
_AT_@ -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
_AT_@ -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
_AT_@ -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
_AT_@ -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);
Received on Wed Mar 11 2015 - 13:42:33 CET

This archive was generated by hypermail 2.3.0 : Wed Mar 11 2015 - 13:48:12 CET