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.
This commit is contained in:
parent
3b825735d8
commit
3c33abc520
1
Makefile
1
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\
|
||||
|
2
col.c
2
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);
|
||||
}
|
||||
|
2
cut.c
2
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;
|
||||
|
8
find.c
8
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;
|
||||
|
50
libutil/mallocarray.c
Normal file
50
libutil/mallocarray.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Otto Moerbeek <otto@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;
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
|
4
ls.c
4
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);
|
||||
|
8
paste.c
8
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)
|
||||
|
4
printf.c
4
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, "<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
|
||||
|
5
sed.c
5
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);
|
||||
|
@ -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;
|
||||
|
6
tr.c
6
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] == '[') {
|
||||
|
2
util.h
2
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);
|
||||
|
Loading…
Reference in New Issue
Block a user