tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

reallocarr(3)



Hi all,
as discussed in the recent strtonum thread, I believe that reallocarray
is wrong in the way it makes error handling more complicated to get
right. Attached is an alternative, including modifications for regcomp.c
for an IMO better interface. There is one issue with reallocarr(3) and
that's related to the C type system. Sadly, void ** and foo ** are not
implicit cast compatible, that's why the prototype takes a void *
argument.

Joerg
Index: distrib/sets/lists/comp/mi
===================================================================
RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/comp/mi,v
retrieving revision 1.1945
diff -u -p -r1.1945 mi
--- distrib/sets/lists/comp/mi	5 Feb 2015 16:07:15 -0000	1.1945
+++ distrib/sets/lists/comp/mi	5 Feb 2015 19:21:55 -0000
@@ -8765,6 +8765,7 @@
 ./usr/share/man/cat3/re_exec.0			comp-c-catman		.cat
 ./usr/share/man/cat3/readdir.0			comp-c-catman		.cat
 ./usr/share/man/cat3/readdir_r.0		comp-c-catman		.cat
+./usr/share/man/cat3/reallocarr.0		comp-c-catman		.cat
 ./usr/share/man/cat3/reallocarray.0		comp-c-catman		.cat
 ./usr/share/man/cat3/realloc.0			comp-c-catman		.cat
 ./usr/share/man/cat3/realpath.0			comp-c-catman		.cat
@@ -15605,6 +15606,7 @@
 ./usr/share/man/html3/re_exec.html		comp-c-htmlman		html
 ./usr/share/man/html3/readdir.html		comp-c-htmlman		html
 ./usr/share/man/html3/readdir_r.html		comp-c-htmlman		html
+./usr/share/man/html3/reallocarr.html		comp-c-htmlman		html
 ./usr/share/man/html3/reallocarray.html		comp-c-htmlman		html
 ./usr/share/man/html3/realloc.html		comp-c-htmlman		html
 ./usr/share/man/html3/realpath.html		comp-c-htmlman		html
@@ -22444,6 +22446,7 @@
 ./usr/share/man/man3/re_exec.3			comp-c-man		.man
 ./usr/share/man/man3/readdir.3			comp-c-man		.man
 ./usr/share/man/man3/readdir_r.3		comp-c-man		.man
+./usr/share/man/man3/reallocarr.3		comp-c-man		.man
 ./usr/share/man/man3/reallocarray.3		comp-c-man		.man
 ./usr/share/man/man3/realloc.3			comp-c-man		.man
 ./usr/share/man/man3/realpath.3			comp-c-man		.man
Index: include/stdlib.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/include/stdlib.h,v
retrieving revision 1.113
diff -u -p -r1.113 stdlib.h
--- include/stdlib.h	5 Feb 2015 16:05:46 -0000	1.113
+++ include/stdlib.h	5 Feb 2015 18:30:31 -0000
@@ -125,6 +125,7 @@ unsigned long
 	 strtoul(const char * __restrict, char ** __restrict, int);
 #ifdef _OPENBSD_SOURCE
 long long strtonum(const char *, long long, long long, const char **);
+void	*reallocarray(void *, size_t, size_t);
 #endif
 int	 system(const char *);
 
@@ -337,6 +338,8 @@ int	 l64a_r(long, char *, int);
 
 size_t	shquote(const char *, char *, size_t);
 size_t	shquotev(int, char * const *, char *, size_t);
+
+int	reallocarr(void *, size_t, size_t);
 #endif /* _NETBSD_SOURCE */
 #endif /* _POSIX_C_SOURCE || _XOPEN_SOURCE || _NETBSD_SOURCE */
 
@@ -364,7 +367,6 @@ unsigned long long int
 	strtoull_l(const char * __restrict, char ** __restrict, int, locale_t);
 
 #  if defined(_NETBSD_SOURCE)
-void	*reallocarray(void *, size_t, size_t);
 quad_t	 strtoq_l(const char * __restrict, char ** __restrict, int, locale_t);
 u_quad_t strtouq_l(const char * __restrict, char ** __restrict, int, locale_t);
 
Index: lib/libc/include/namespace.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/include/namespace.h,v
retrieving revision 1.176
diff -u -p -r1.176 namespace.h
--- lib/libc/include/namespace.h	26 Sep 2014 19:28:03 -0000	1.176
+++ lib/libc/include/namespace.h	5 Feb 2015 17:25:46 -0000
@@ -547,6 +547,7 @@
 #define readdir			_readdir
 #define readdir_r		_readdir_r
 #define readlink		_readlink
+#define reallocarr		_reallocarr
 #define realpath		_realpath
 #define regcomp			_regcomp
 #define regerror		_regerror
Index: lib/libc/regex/regcomp.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/regex/regcomp.c,v
retrieving revision 1.34
diff -u -p -r1.34 regcomp.c
--- lib/libc/regex/regcomp.c	5 Feb 2015 16:04:35 -0000	1.34
+++ lib/libc/regex/regcomp.c	5 Feb 2015 18:10:17 -0000
@@ -81,7 +81,6 @@ __RCSID("$NetBSD: regcomp.c,v 1.34 2015/
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
-#include <sys/param.h>
 #include <sys/types.h>
 
 #include <assert.h>
@@ -267,7 +266,7 @@ regcomp(
 	if (g == NULL)
 		return(REG_ESPACE);
 	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
-	p->strip = reallocarray(NULL, p->ssize, sizeof(sop));
+	p->strip = calloc(p->ssize, sizeof(sop));
 	p->slen = 0;
 	if (p->strip == NULL) {
 		free(g);
@@ -1236,6 +1235,7 @@ allocset(
 	cset *cs;
 	size_t css;
 	size_t i;
+	void *old_ptr;
 
 	_DIAGASSERT(p != NULL);
 
@@ -1248,29 +1248,18 @@ allocset(
 		nbytes = nc / CHAR_BIT * css;
 		if (MEMSIZE(p) > MEMLIMIT)
 			goto oomem;
-		if (p->g->sets == NULL)
-			p->g->sets = reallocarray(NULL, nc, sizeof(cset));
-		else
-			p->g->sets = reallocarray(p->g->sets, nc, sizeof(cset));
-		if (p->g->setbits == NULL)
-			p->g->setbits = malloc(nbytes);
-		else {
-			p->g->setbits = realloc(p->g->setbits, nbytes);
-			if (p->g->setbits == NULL)
-				goto oomem;
+		if (reallocarr(&p->g->sets, nc, sizeof(cset)))
+			goto oomem;
+		old_ptr = p->g->setbits;
+		if (reallocarr(&p->g->setbits, nc / CHAR_BIT, css)) {
+			free(old_ptr);
+			goto oomem;
+		}
+		if (old_ptr != p->g->setbits) {
 			for (i = 0; i < no; i++)
 				p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
 		}
-		if (p->g->sets != NULL && p->g->setbits != NULL)
-			(void) memset((char *)p->g->setbits + (nbytes - css),
-								0, css);
-		else {
-oomem:
-			no = 0;
-			SETERROR(REG_ESPACE);
-			/* caller's responsibility not to do set ops */
-			return NULL;
-		}
+		(void) memset((char *)p->g->setbits + (nbytes - css), 0, css);
 	}
 
 	cs = &p->g->sets[no];
@@ -1281,6 +1270,11 @@ oomem:
 	cs->multis = NULL;
 
 	return(cs);
+
+oomem:
+	SETERROR(REG_ESPACE);
+	/* caller's responsibility not to do set ops */
+	return NULL;
 }
 
 /*
@@ -1764,30 +1758,18 @@ dofwd(
  == static void enlarge(struct parse *p, sopno size);
  */
 static int
-enlarge(
-    struct parse *p,
-    sopno size)
+enlarge(struct parse *p, sopno size)
 {
-	sop *sp;
-	sopno osize;
-
 	_DIAGASSERT(p != NULL);
 
 	if (p->ssize >= size)
 		return 1;
 
-	osize = p->ssize;
-	p->ssize = size;
-	if (MEMSIZE(p) > MEMLIMIT)
-		goto oomem;
-	sp = reallocarray(p->strip, p->ssize, sizeof(sop));
-	if (sp == NULL) {
-oomem:
-		p->ssize = osize;
+	if (MEMSIZE(p) > MEMLIMIT || reallocarr(&p->strip, size, sizeof(sop))) {
 		SETERROR(REG_ESPACE);
 		return 0;
 	}
-	p->strip = sp;
+	p->ssize = size;
 	return 1;
 }
 
@@ -1805,11 +1787,9 @@ stripsnug(
 	_DIAGASSERT(g != NULL);
 
 	g->nstates = p->slen;
-	g->strip = reallocarray(p->strip, p->slen, sizeof(sop));
-	if (g->strip == NULL) {
-		SETERROR(REG_ESPACE);
-		g->strip = p->strip;
-	}
+	g->strip = p->strip;
+	reallocarr(&g->strip, p->slen, sizeof(sop));
+	/* Ignore error as tries to free memory only. */
 }
 
 /*
Index: lib/libc/stdlib/Makefile.inc
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/stdlib/Makefile.inc,v
retrieving revision 1.87
diff -u -p -r1.87 Makefile.inc
--- lib/libc/stdlib/Makefile.inc	5 Feb 2015 16:04:35 -0000	1.87
+++ lib/libc/stdlib/Makefile.inc	5 Feb 2015 17:05:50 -0000
@@ -12,7 +12,7 @@ SRCS+=	_env.c _rand48.c \
 	lcong48.c lrand48.c lsearch.c merge.c mi_vector_hash.c mrand48.c \
 	nrand48.c putenv.c qabs.c qdiv.c qsort.c posix_openpt.c pty.c \
 	quick_exit.c radixsort.c rand.c rand_r.c random.c remque.c \
-	reallocarray.c seed48.c setenv.c srand48.c strsuftoll.c \
+	reallocarr.c reallocarray.c seed48.c setenv.c srand48.c strsuftoll.c \
 	strtoi.c strtou.c strtonum.c \
 	strtoimax.c strtol.c strtoll.c strtoq.c strtoul.c strtoull.c \
 	strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c \
@@ -52,7 +52,7 @@ MAN+=	a64l.3 abort.3 abs.3 alloca.3 atex
 	malloc.3 memory.3 mi_vector_hash.3 \
 	posix_memalign.3 posix_openpt.3 ptsname.3 \
 	qabs.3 qdiv.3 quick_exit.3 qsort.3 \
-	radixsort.3 rand48.3 rand.3 random.3 \
+	radixsort.3 rand48.3 rand.3 random.3 reallocarr.3 \
 	strfmon.3 strsuftoll.3 strtod.3 strtol.3 strtoul.3 strtonum.3 \
 	system.3 \
 	tsearch.3 \
Index: lib/libc/stdlib/reallocarr.3
===================================================================
RCS file: lib/libc/stdlib/reallocarr.3
diff -N lib/libc/stdlib/reallocarr.3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/libc/stdlib/reallocarr.3	5 Feb 2015 19:20:22 -0000
@@ -0,0 +1,67 @@
+.\"	$NetBSD$
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``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
+.\" COPYRIGHT HOLDERS OR CONTRIBUTORS 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.
+.Dd February 5, 2015
+.Dt REALLOCARR 3
+.Os
+.Sh NAME
+.Nm reallocarr
+.Nd reallocate array
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fo reallocarr
+.Fa "void *ptr"
+.Fa "size_t num"
+.Fa "size_t size"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+function reallocates the memory in
+.Fa *ptr .
+.Sh RETURN VALUES
+On successful completion,
+.Fn
+returns 0 and updates
+.Fa *ptr .
+Otherwise, an error code (see
+.Xr errno 7 )
+is returned and
+.Fa *ptr
+and the referenced memory is unmodified.
+.Sh SEE ALSO
+.Xr calloc 3
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 7.0 .
+.Ox introduced the
+.Xr reallocarray 3
+function for the same purpose, but the interface makes it difficult
+to correctly handle zero-sized allocations.
Index: lib/libc/stdlib/reallocarr.c
===================================================================
RCS file: lib/libc/stdlib/reallocarr.c
diff -N lib/libc/stdlib/reallocarr.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/libc/stdlib/reallocarr.c	5 Feb 2015 18:17:29 -0000
@@ -0,0 +1,78 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015 Joerg Sonnenberger <joerg%NetBSD.org@localhost>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS 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 <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+/* Old POSIX has SIZE_MAX in limits.h */
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+__CTASSERT(65535 < SIZE_MAX / 65535);
+
+#ifdef _LIBC
+#ifdef __weak_alias
+__weak_alias(reallocarr, _reallocarr)
+#endif
+#endif
+
+int
+reallocarr(void *ptr, size_t num, size_t size)
+{
+	int saved_errno, result;
+	void *optr;
+	void *nptr;
+
+	memcpy(&optr, ptr, sizeof(ptr));
+	saved_errno = errno;
+	if (num == 0 || size == 0) {
+		free(optr);
+		nptr = NULL;
+		memcpy(ptr, &nptr, sizeof(ptr));
+		errno = saved_errno;
+		return 0;
+	}
+	if ((num >= 65535 || size >= 65535) && num > SIZE_MAX / size)
+		return EOVERFLOW;
+	nptr = realloc(optr, num * size);
+	if (nptr == NULL) {
+		result = errno;
+	} else {
+		result = 0;
+		memcpy(ptr, &nptr, sizeof(ptr));
+	}
+	errno = saved_errno;
+	return result;
+}
Index: lib/libc/stdlib/reallocarray.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/stdlib/reallocarray.c,v
retrieving revision 1.1
diff -u -p -r1.1 reallocarray.c
--- lib/libc/stdlib/reallocarray.c	5 Feb 2015 16:04:35 -0000	1.1
+++ lib/libc/stdlib/reallocarray.c	5 Feb 2015 18:34:45 -0000
@@ -14,6 +14,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#define _OPENBSD_SOURCE
 #include <sys/cdefs.h>
 __RCSID("$NetBSD: reallocarray.c,v 1.1 2015/02/05 16:04:35 christos Exp $");
 


Home | Main Index | Thread Index | Old Index