aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-01-21 15:37:02 +0000
committerOmar Polo <op@omarpolo.com>2021-01-21 15:37:02 +0000
commit5c342d059f884b73823e5a466902a3826b17e6c7 (patch)
tree82915c2da7cb8dc82823906b5373cfbaa675fdc6
parentb2a6b6137186dd3fce21640150926a133a35c2c8 (diff)
more OpenBSD goodies
-rw-r--r--compat/explicit_bzero.c12
-rw-r--r--compat/recallocarray.c91
-rw-r--r--compat/strtonum.c64
-rwxr-xr-xconfigure23
-rw-r--r--have/explicit_bzero.c10
-rw-r--r--have/recallocarray.c11
-rw-r--r--have/strtonum.c27
7 files changed, 236 insertions, 2 deletions
diff --git a/compat/explicit_bzero.c b/compat/explicit_bzero.c
new file mode 100644
index 0000000..674b8e2
--- /dev/null
+++ b/compat/explicit_bzero.c
@@ -0,0 +1,12 @@
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include <string.h>
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+ memset(buf, 0, len);
+}
diff --git a/compat/recallocarray.c b/compat/recallocarray.c
new file mode 100644
index 0000000..1baffbb
--- /dev/null
+++ b/compat/recallocarray.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2008, 2017 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 <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.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 ((size_t)1 << (sizeof(size_t) * 4))
+
+/*
+ * Even though specified in POSIX, the PAGESIZE and PAGE_SIZE
+ * macros have very poor portability. Since we only use this
+ * to avoid free() overhead for small shrinking, simply pick
+ * an arbitrary number.
+ */
+#define getpagesize() (1UL << 12)
+
+/* cheat: provide a prototype for explicit_bzero: if libc doesn't
+ * provide it, we will link to compat/explicit_bzero.c anyway. */
+void explicit_bzero(void*, size_t);
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+ size_t oldsize, newsize;
+ void *newptr;
+
+ if (ptr == NULL)
+ return calloc(newnmemb, size);
+
+ if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ newsize = newnmemb * size;
+
+ if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+ errno = EINVAL;
+ return NULL;
+ }
+ oldsize = oldnmemb * size;
+
+ /*
+ * Don't bother too much if we're shrinking just a bit,
+ * we do not shrink for series of small steps, oh well.
+ */
+ if (newsize <= oldsize) {
+ size_t d = oldsize - newsize;
+
+ if (d < oldsize / 2 && d < getpagesize()) {
+ memset((char *)ptr + newsize, 0, d);
+ return ptr;
+ }
+ }
+
+ newptr = malloc(newsize);
+ if (newptr == NULL)
+ return NULL;
+
+ if (newsize > oldsize) {
+ memcpy(newptr, ptr, oldsize);
+ memset((char *)newptr + oldsize, 0, newsize - oldsize);
+ } else
+ memcpy(newptr, ptr, newsize);
+
+ explicit_bzero(ptr, oldsize);
+ free(ptr);
+
+ return newptr;
+}
diff --git a/compat/strtonum.c b/compat/strtonum.c
new file mode 100644
index 0000000..6e6cb76
--- /dev/null
+++ b/compat/strtonum.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * 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 "config.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ int error = 0;
+ char *ep;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval) {
+ error = INVALID;
+ } else {
+ ll = strtoll(numstr, &ep, 10);
+ if (numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
diff --git a/configure b/configure
index 194acf6..7bacd2a 100755
--- a/configure
+++ b/configure
@@ -41,10 +41,13 @@ LEX=lex
STATIC=
HAVE_ERR=
+HAVE_EXPLICIT_BZERO=
HAVE_GETPROGNAME=
HAVE_LIBTLS=
+HAVE_RECALLOCARRAY=
HAVE_STRLCAT=
HAVE_STRLCPY=
+HAVE_STRTONUM=
HAVE_VASPRINTF=
NEED_GNU_SOURCE=0
@@ -223,9 +226,12 @@ fi
# tests for config.h
runtest err ERR || true
+runtest explicit_bzero EXPLICIT_BZERO || true
runtest libtls LIBTLS || true
+runtest recallocarray RECALLOCARRAY || true
runtest strlcat STRLCAT || true
runtest strlcpy STRLCPY || true
+runtest strtonum STRTONUM || true
runtest vasprintf VASPRINTF "" -D_GNU_SOURCE || true
if [ ${HAVE_LIBTLS} -eq 0 ]; then
@@ -243,7 +249,6 @@ cat <<__HEREDOC__
#ifdef __cplusplus
#error "Do not use C++."
#endif
-
__HEREDOC__
[ ${NEED_GNU_SOURCE} -eq 0 ] || echo "#define _GNU_SOURCE"
@@ -256,9 +261,12 @@ __HEREDOC__
cat <<__HEREDOC__
#define HAVE_ERR ${HAVE_ERR}
+#define HAVE_EXPLICIT_BZERO ${HAVE_EXPLICIT_BZERO}
#define HAVE_GETPROGNAME ${HAVE_GETPROGNAME}
+#define HAVE_RECALLOCARRAY ${HAVE_RECALLOCARRAY}
#define HAVE_STRLCAT ${HAVE_STRLCAT}
#define HAVE_STRLCPY ${HAVE_STRLCPY}
+#define HAVE_STRTONUM ${HAVE_STRTONUM}
#define HAVE_VASPRINTF ${HAVE_VASPRINTF}
__HEREDOC__
@@ -270,7 +278,14 @@ if [ ${HAVE_ERR} -eq 0 ]; then
echo "extern void warnx(const char*, ...);"
COMPAT="${COMPAT} compat/err.o"
fi
-
+if [ ${HAVE_EXPLICIT_BZERO} -eq 0 ]; then
+ echo "extern void explicit_bzero(void*, size_t);"
+ COMPAT="${COMPAT} compat/explicit_bzero.o"
+fi
+if [ ${HAVE_RECALLOCARRAY} -eq 0 ]; then
+ echo "extern void* recallocarray(void*, size_t, size_t, size_t);"
+ COMPAT="${COMPAT} compat/recallocarray.o"
+fi
if [ ${HAVE_STRLCAT} -eq 0 ]; then
echo "extern size_t strlcat(char*, const char*, size_t);"
COMPAT="${COMPAT} compat/strlcat.o"
@@ -279,6 +294,10 @@ if [ ${HAVE_STRLCPY} -eq 0 ]; then
echo "extern size_t strlcpy(char*, const char*, size_t);"
COMPAT="${COMPAT} compat/strlcpy.o"
fi
+if [ ${HAVE_STRTONUM} -eq 0 ]; then
+ echo "extern long long strtonum(const char*, long long, long long, const char**)"
+ COMPAT="${COMPAT} compat/strtonum.o"
+fi
if [ ${HAVE_VASPRINTF} -eq 0 ]; then
echo "extern int vasprintf(char**, const char*, va_list);"
COMPAT="${COMPAT} compat/vasprintf.o"
diff --git a/have/explicit_bzero.c b/have/explicit_bzero.c
new file mode 100644
index 0000000..9e8bd70
--- /dev/null
+++ b/have/explicit_bzero.c
@@ -0,0 +1,10 @@
+#include <string.h>
+
+int
+main(void)
+{
+ char buf[] = "hello world";
+
+ explicit_bzero(buf, sizeof(buf));
+ return strcmp(buf, "");
+}
diff --git a/have/recallocarray.c b/have/recallocarray.c
new file mode 100644
index 0000000..e0c60d7
--- /dev/null
+++ b/have/recallocarray.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+
+int
+main(void)
+{
+ void *p;
+
+ if ((p = calloc(2, 2)) == NULL)
+ return 1;
+ return !recallocarray(p, 2, 3, 2);
+}
diff --git a/have/strtonum.c b/have/strtonum.c
new file mode 100644
index 0000000..6e2aad2
--- /dev/null
+++ b/have/strtonum.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ *
+ * 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 <stdlib.h>
+
+int
+main(void)
+{
+ const char *str = "42", *errstr;
+ int res;
+
+ res = strtonum(str, 1, 64, &errstr);
+ return res != 42 || errstr != NULL;
+}