more OpenBSD goodies

This commit is contained in:
Omar Polo 2021-01-21 15:37:02 +00:00
parent b2a6b61371
commit 5c342d059f
7 changed files with 236 additions and 2 deletions

12
compat/explicit_bzero.c Normal file
View File

@ -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);
}

91
compat/recallocarray.c Normal file
View File

@ -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;
}

64
compat/strtonum.c Normal file
View File

@ -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);
}

23
configure vendored
View File

@ -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"

10
have/explicit_bzero.c Normal file
View File

@ -0,0 +1,10 @@
#include <string.h>
int
main(void)
{
char buf[] = "hello world";
explicit_bzero(buf, sizeof(buf));
return strcmp(buf, "");
}

11
have/recallocarray.c Normal file
View File

@ -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);
}

27
have/strtonum.c Normal file
View File

@ -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;
}