diff options
author | Russ Allbery <eagle@eyrie.org> | 2014-06-15 16:25:12 -0700 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2014-06-15 17:29:08 -0700 |
commit | 8939c44544383c586a54e4c710a274390e067eed (patch) | |
tree | 25c267e076c294641190851aa413882c87fa9d41 /util | |
parent | c1ece5c6ee75aa2892120ba78ac3a753121a8265 (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.c | 2 | ||||
-rw-r--r-- | util/network.c | 41 | ||||
-rw-r--r-- | util/vector.c | 5 | ||||
-rw-r--r-- | util/xmalloc.c | 20 | ||||
-rw-r--r-- | util/xmalloc.h | 6 | ||||
-rw-r--r-- | util/xwrite.c | 14 |
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)); |