summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorRuss Allbery <eagle@eyrie.org>2014-06-15 16:25:12 -0700
committerRuss Allbery <rra@stanford.edu>2014-06-15 17:29:08 -0700
commit8939c44544383c586a54e4c710a274390e067eed (patch)
tree25c267e076c294641190851aa413882c87fa9d41 /util
parentc1ece5c6ee75aa2892120ba78ac3a753121a8265 (diff)
Update to rra-c-util 5.5 and C TAP Harness 3.1
Update to rra-c-util 5.5: * Use calloc or reallocarray for protection against integer overflows. * Suppress warnings from Kerberos headers in non-system paths. Update to C TAP Harness 3.1: * Add breallocarray API for error-checked reallocarray in tests. * Check for integer overflow on memory allocations. Change-Id: Ib2f407c1d65ed4e8a4abbe45e0db543dd9ac07ba Reviewed-on: https://gerrit.stanford.edu/1489 Reviewed-by: Russ Allbery <rra@stanford.edu> Tested-by: Russ Allbery <rra@stanford.edu>
Diffstat (limited to 'util')
-rw-r--r--util/messages.c2
-rw-r--r--util/network.c41
-rw-r--r--util/vector.c5
-rw-r--r--util/xmalloc.c20
-rw-r--r--util/xmalloc.h6
-rw-r--r--util/xwrite.c14
6 files changed, 68 insertions, 20 deletions
diff --git a/util/messages.c b/util/messages.c
index 4dac823..a43d962 100644
--- a/util/messages.c
+++ b/util/messages.c
@@ -131,7 +131,7 @@ message_handlers(message_handler_func **list, unsigned int count, va_list args)
if (*list != stdout_handlers && *list != stderr_handlers)
free(*list);
- *list = xmalloc(sizeof(message_handler_func) * (count + 1));
+ *list = xcalloc(count + 1, sizeof(message_handler_func));
for (i = 0; i < count; i++)
(*list)[i] = (message_handler_func) va_arg(args, message_handler_func);
(*list)[count] = NULL;
diff --git a/util/network.c b/util/network.c
index 5f4d746..c10ffe7 100644
--- a/util/network.c
+++ b/util/network.c
@@ -20,7 +20,7 @@
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
* Written by Russ Allbery <eagle@eyrie.org>
- * Copyright 2009, 2011, 2012, 2013
+ * Copyright 2009, 2011, 2012, 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006, 2007, 2008
* by Internet Systems Consortium, Inc. ("ISC")
@@ -328,7 +328,7 @@ network_bind_all(int type, unsigned short port, socket_type **fds,
* assuming an IPv6 and IPv4 socket, and grow it by two when necessary.
*/
size = 2;
- *fds = xmalloc(size * sizeof(socket_type));
+ *fds = xcalloc(size, sizeof(socket_type));
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
network_sockaddr_sprint(name, sizeof(name), addr->ai_addr);
if (addr->ai_family == AF_INET)
@@ -340,7 +340,7 @@ network_bind_all(int type, unsigned short port, socket_type **fds,
if (fd != INVALID_SOCKET) {
if (*count >= size) {
size += 2;
- *fds = xrealloc(*fds, size * sizeof(socket_type));
+ *fds = xreallocarray(*fds, size, sizeof(socket_type));
}
(*fds)[*count] = fd;
(*count)++;
@@ -712,7 +712,12 @@ network_read(socket_type fd, void *buffer, size_t total, time_t timeout)
if (timeout == 0)
return (socket_xread(fd, buffer, total) >= 0);
- /* The hard way. We try to apply the timeout on the whole read. */
+ /*
+ * The hard way. We try to apply the timeout on the whole read. If
+ * either select or read fails with EINTR, restart the loop, and rely on
+ * the overall timeout to limit how long we wait without forward
+ * progress.
+ */
start = time(NULL);
now = start;
do {
@@ -723,16 +728,20 @@ network_read(socket_type fd, void *buffer, size_t total, time_t timeout)
tv.tv_sec = 1;
tv.tv_usec = 0;
status = select(fd + 1, &set, NULL, NULL, &tv);
- if (status < 0)
+ if (status < 0) {
+ if (socket_errno == EINTR)
+ continue;
return false;
- else if (status == 0) {
+ } else if (status == 0) {
socket_set_errno(ETIMEDOUT);
return false;
}
status = socket_read(fd, (char *) buffer + got, total - got);
- if (status < 0)
+ if (status < 0) {
+ if (socket_errno == EINTR)
+ continue;
return false;
- else if (status == 0) {
+ } else if (status == 0) {
socket_set_errno(EPIPE);
return false;
}
@@ -767,7 +776,10 @@ network_write(socket_type fd, const void *buffer, size_t total, time_t timeout)
if (timeout == 0)
return (socket_xwrite(fd, buffer, total) >= 0);
- /* The hard way. We try to apply the timeout on the whole write. */
+ /* The hard way. We try to apply the timeout on the whole write. If
+ * either select or read fails with EINTR, restart the loop, and rely on
+ * the overall timeout to limit how long we wait without forward progress.
+ */
fdflag_nonblocking(fd, true);
start = time(NULL);
now = start;
@@ -779,15 +791,20 @@ network_write(socket_type fd, const void *buffer, size_t total, time_t timeout)
tv.tv_sec = 1;
tv.tv_usec = 0;
status = select(fd + 1, NULL, &set, NULL, &tv);
- if (status < 0)
+ if (status < 0) {
+ if (socket_errno == EINTR)
+ continue;
goto fail;
- else if (status == 0) {
+ } else if (status == 0) {
socket_set_errno(ETIMEDOUT);
goto fail;
}
status = socket_write(fd, (const char *) buffer + sent, total - sent);
- if (status < 0)
+ if (status < 0) {
+ if (socket_errno == EINTR)
+ continue;
goto fail;
+ }
sent += status;
if (sent == total) {
fdflag_nonblocking(fd, false);
diff --git a/util/vector.c b/util/vector.c
index cdd70f7..21ee94e 100644
--- a/util/vector.c
+++ b/util/vector.c
@@ -87,7 +87,7 @@ vector_resize(struct vector *vector, size_t size)
}
if (size == 0)
size = 1;
- vector->strings = xrealloc(vector->strings, size * sizeof(char *));
+ vector->strings = xreallocarray(vector->strings, size, sizeof(char *));
vector->allocated = size;
}
@@ -99,7 +99,8 @@ cvector_resize(struct cvector *vector, size_t size)
vector->count = size;
if (size == 0)
size = 1;
- vector->strings = xrealloc(vector->strings, size * sizeof(const char *));
+ vector->strings
+ = xreallocarray(vector->strings, size, sizeof(const char *));
vector->allocated = size;
}
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 5bfd555..721447a 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -33,6 +33,10 @@
* allocation function will try its allocation again (calling the handler
* again if it still fails).
*
+ * xreallocarray behaves the same as the OpenBSD reallocarray function but for
+ * the same error checking, which in turn is the same as realloc but with
+ * calloc-style arguments and size overflow checking.
+ *
* xstrndup behaves like xstrdup but only copies the given number of
* characters. It allocates an additional byte over its second argument and
* always nul-terminates the string.
@@ -58,7 +62,7 @@
* The canonical version of this file is maintained in the rra-c-util package,
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * Copyright 2012, 2013
+ * Copyright 2012, 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
@@ -152,6 +156,20 @@ x_realloc(void *p, size_t size, const char *file, int line)
}
+void *
+x_reallocarray(void *p, size_t n, size_t size, const char *file, int line)
+{
+ void *newp;
+
+ newp = reallocarray(p, n, size);
+ while (newp == NULL && size > 0 && n > 0) {
+ (*xmalloc_error_handler)("reallocarray", n * size, file, line);
+ newp = reallocarray(p, n, size);
+ }
+ return newp;
+}
+
+
char *
x_strdup(const char *s, const char *file, int line)
{
diff --git a/util/xmalloc.h b/util/xmalloc.h
index ac4d796..a4b4686 100644
--- a/util/xmalloc.h
+++ b/util/xmalloc.h
@@ -4,7 +4,7 @@
* The canonical version of this file is maintained in the rra-c-util package,
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * Copyright 2010, 2012, 2013
+ * Copyright 2010, 2012, 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
@@ -47,6 +47,8 @@
#define xstrdup(p) x_strdup((p), __FILE__, __LINE__)
#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__)
#define xvasprintf(p, f, a) x_vasprintf((p), (f), (a), __FILE__, __LINE__)
+#define xreallocarray(p, n, size) \
+ x_reallocarray((p), (n), (size), __FILE__, __LINE__)
/*
* asprintf is a special case since it takes variable arguments. If we have
@@ -81,6 +83,8 @@ void *x_malloc(size_t, const char *, int)
__attribute__((__alloc_size__(1), __malloc__, __nonnull__));
void *x_realloc(void *, size_t, const char *, int)
__attribute__((__alloc_size__(2), __malloc__, __nonnull__(3)));
+void *x_reallocarray(void *, size_t, size_t, const char *, int)
+ __attribute__((__alloc_size__(2, 3), __malloc__, __nonnull__(4)));
char *x_strdup(const char *, const char *, int)
__attribute__((__malloc__, __nonnull__));
char *x_strndup(const char *, size_t, const char *, int)
diff --git a/util/xwrite.c b/util/xwrite.c
index d1cb6cf..562bd27 100644
--- a/util/xwrite.c
+++ b/util/xwrite.c
@@ -24,7 +24,7 @@
* The canonical version of this file is maintained in the rra-c-util package,
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * Copyright 2008, 2013
+ * Copyright 2008, 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
@@ -137,13 +137,21 @@ xwritev(int fd, const struct iovec iov[], int iovcnt)
int iovleft, i, count;
struct iovec *tmpiov;
+ /*
+ * Bounds-check the iovcnt argument. This is just for our safety. The
+ * system will probably impose a lower limit on iovcnt, causing the later
+ * writev to fail with an error we'll return.
+ */
if (iovcnt == 0)
return 0;
+ if (iovcnt < 0 || (size_t) iovcnt > SIZE_MAX / sizeof(struct iovec)) {
+ errno = EINVAL;
+ return -1;
+ }
/* Get a count of the total number of bytes in the iov array. */
for (total = 0, i = 0; i < iovcnt; i++)
total += iov[i].iov_len;
-
if (total == 0)
return 0;
@@ -177,7 +185,7 @@ xwritev(int fd, const struct iovec iov[], int iovcnt)
offset -= iov[i].iov_len;
iovleft = iovcnt - i;
assert(iovleft > 0);
- tmpiov = malloc(iovleft * sizeof(struct iovec));
+ tmpiov = calloc(iovleft, sizeof(struct iovec));
if (tmpiov == NULL)
return -1;
memcpy(tmpiov, iov + i, iovleft * sizeof(struct iovec));