summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorRuss Allbery <eagle@eyrie.org>2015-09-04 22:21:31 -0700
committerRuss Allbery <eagle@eyrie.org>2015-09-04 22:21:31 -0700
commitf74ab497a7489d7b0bf1f517d72bbd0e7d382031 (patch)
tree1f78c15afdb729aff58cf1543fa5cbf80bc9bc9f /util
parent1899f8815bd606790b8e88a6a43651cac911166e (diff)
Update to rra-c-util 5.8 and C TAP Harness 3.4
Update to rra-c-util 5.8: * Add missing va_end to xasprintf implementation. * Fix Perl test suite framework for new Automake relative paths. * Avoid $() in the probe for systemd support for Solaris portability. * Prefer libsystemd to libsystemd-daemon if it is available. * Improve portability to Kerberos included in Solaris 10. * Use appropriate warning flags with Clang (currently not warning clean). * Check for integer overflow in vector_join. * Avoid strlcpy in more of the portability code. * Fix hidden visibility of some utility functions. * Improve portability of socket error codes to Windows. Update to C TAP Harness 3.4: * Fix segfault in runtests with an empty test list. * Display verbose test results with -v or C_TAP_VERBOSE. * Support comments and blank lines in test lists.
Diffstat (limited to 'util')
-rw-r--r--util/fdflag.c7
-rw-r--r--util/macros.h4
-rw-r--r--util/messages.c2
-rw-r--r--util/messages.h19
-rw-r--r--util/network.c46
-rw-r--r--util/network.h19
-rw-r--r--util/vector.c40
-rw-r--r--util/vector.h2
-rw-r--r--util/xmalloc.c2
-rw-r--r--util/xmalloc.h2
-rw-r--r--util/xwrite.c15
-rw-r--r--util/xwrite.h2
12 files changed, 97 insertions, 63 deletions
diff --git a/util/fdflag.c b/util/fdflag.c
index 828a841..3be61a5 100644
--- a/util/fdflag.c
+++ b/util/fdflag.c
@@ -58,7 +58,10 @@
* Do it right anyway; it's not that expensive.
*
* Stub this out on Windows, where it's not supported (at least currently by
- * this utility library).
+ * this utility library). Do not use socket_type for the first parameter,
+ * since it's meaningful to set file descriptors for regular files to
+ * close-on-exec (even though this is currently irrelevant since the function
+ * isn't supported on Windows).
*/
#ifdef _WIN32
bool
@@ -144,6 +147,6 @@ fdflag_nonblocking(socket_type fd, bool flag)
int state;
state = flag ? 1 : 0;
- return ioctl(fd, FIONBIO, &state);
+ return (ioctl(fd, FIONBIO, &state) == 0);
}
#endif /* !O_NONBLOCK */
diff --git a/util/macros.h b/util/macros.h
index d071793..4a773a2 100644
--- a/util/macros.h
+++ b/util/macros.h
@@ -29,6 +29,10 @@
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#define ARRAY_END(array) (&(array)[ARRAY_SIZE(array)])
+/* Used to name the elements of the array passed to pipe. */
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
/* Used for unused parameters to silence gcc warnings. */
#define UNUSED __attribute__((__unused__))
diff --git a/util/messages.c b/util/messages.c
index a43d962..b5c2dba 100644
--- a/util/messages.c
+++ b/util/messages.c
@@ -225,7 +225,7 @@ message_log_stderr(size_t len UNUSED, const char *fmt, va_list args, int err)
* This needs further attention on Windows. For example, it currently doesn't
* log the errno information.
*/
-static void
+static void __attribute__((__format__(printf, 3, 0)))
message_log_syslog(int pri, size_t len, const char *fmt, va_list args, int err)
{
char *buffer;
diff --git a/util/messages.h b/util/messages.h
index 8c731b7..cf91ba7 100644
--- a/util/messages.h
+++ b/util/messages.h
@@ -84,24 +84,25 @@ void message_handlers_reset(void);
* argument list, and the errno setting if any.
*/
void message_log_stdout(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_stderr(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_debug(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_info(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_notice(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_warning(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_err(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
void message_log_syslog_crit(size_t, const char *, va_list, int)
- __attribute__((__nonnull__));
+ __attribute__((__format__(printf, 2, 0), __nonnull__));
/* The type of a message handler. */
-typedef void (*message_handler_func)(size_t, const char *, va_list, int);
+typedef void (*message_handler_func)(size_t, const char *, va_list, int)
+ __attribute__((__format__(printf, 2, 0)));
/* If non-NULL, called before exit and its return value passed to exit. */
extern int (*message_fatal_cleanup)(void);
diff --git a/util/network.c b/util/network.c
index c10ffe7..07aa067 100644
--- a/util/network.c
+++ b/util/network.c
@@ -20,6 +20,7 @@
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
* Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2014, 2015 Russ Allbery <eagle@eyrie.org>
* Copyright 2009, 2011, 2012, 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006, 2007, 2008
@@ -57,6 +58,7 @@
#include <time.h>
#include <util/fdflag.h>
+#include <util/macros.h>
#include <util/messages.h>
#include <util/network.h>
#include <util/xmalloc.h>
@@ -97,17 +99,6 @@
#endif
/*
- * Windows requires a different errno code for a socket equivalent of EINVAL.
- * Use this macro to set the socket error to EINVAL.
- */
-#ifdef _WIN32
-# define socket_set_errno_einval() socket_set_errno(WSAEINVAL)
-#else
-# define socket_set_errno_einval() socket_set_errno(EINVAL)
-#endif
-
-
-/*
* Set SO_REUSEADDR on a socket if possible (so that something new can listen
* on the same port immediately if the daemon dies unexpectedly).
*/
@@ -223,7 +214,8 @@ network_bind_ipv6(int type, const char *address, unsigned short port)
fd = socket(PF_INET6, type, IPPROTO_IP);
if (fd == INVALID_SOCKET) {
if (socket_errno != EAFNOSUPPORT && socket_errno != EPROTONOSUPPORT)
- syswarn("cannot create IPv6 socket for %s,%hu", address, port);
+ syswarn("cannot create IPv6 socket for %s, port %hu", address,
+ port);
return INVALID_SOCKET;
}
network_set_reuseaddr(fd);
@@ -248,9 +240,13 @@ network_bind_ipv6(int type, const char *address, unsigned short port)
* exist on the system, but we gain the ability to bind to IPv6 addresses
* that aren't yet configured. Since IPv6 address configuration can take
* unpredictable amounts of time during system setup, this is more robust.
+ *
+ * Ensure there is always a block here to avoid compiler warnings, since
+ * network_set_freebind() may expand into nothing.
*/
- if (strcmp(address, "::") != 0)
+ if (strcmp(address, "::") != 0) {
network_set_freebind(fd);
+ }
/* Flesh out the socket and do the bind. */
memset(&server, 0, sizeof(server));
@@ -274,7 +270,7 @@ network_bind_ipv6(int type, const char *address, unsigned short port)
#else /* HAVE_INET6 */
socket_type
-network_bind_ipv6(const char *address, unsigned short port)
+network_bind_ipv6(int type UNUSED, const char *address, unsigned short port)
{
warn("cannot bind %s, port %hu: IPv6 not supported", address, port);
socket_set_errno(EPROTONOSUPPORT);
@@ -287,9 +283,9 @@ network_bind_ipv6(const char *address, unsigned short port)
/*
* Create and bind sockets for every local address, as determined by
* getaddrinfo if IPv6 is available (otherwise, just use the IPv4 loopback
- * address). Takes the port number, and then a pointer to an array of
- * integers and a pointer to a count of them. Allocates a new array to hold
- * the file descriptors and stores the count in the third argument.
+ * address). Takes the socket type and port number, and then a pointer to an
+ * array of integers and a pointer to a count of them. Allocates a new array
+ * to hold the file descriptors and stores the count in the fourth argument.
*/
#if HAVE_INET6
@@ -391,7 +387,7 @@ network_bind_all_free(socket_type *fds)
* on any of those sockets and return the file descriptor that selects ready
* for read.
*
- * This is primarily intended for UDP services listening on mutliple file
+ * This is primarily intended for UDP services listening on multiple file
* descriptors, and also provides part of the code for network_accept_any.
* TCP services will probably want to use network_accept_any instead.
*
@@ -471,7 +467,9 @@ network_accept_any(socket_type fds[], unsigned int count,
static bool
network_source(socket_type fd, int family, const char *source)
{
- if (source == NULL || strcmp(source, "all") == 0)
+ if (source == NULL)
+ return true;
+ if (strcmp(source, "all") == 0 || strcmp(source, "any") == 0)
return true;
if (family == AF_INET) {
struct sockaddr_in saddr;
@@ -669,7 +667,7 @@ socket_xread(socket_type fd, void *buffer, size_t size)
{
size_t total;
ssize_t status;
- int count = 0;
+ unsigned int count = 0;
/* Abort the read if we try 100 times with no forward progress. */
for (total = 0, status = 0; total < size; total += status) {
@@ -955,6 +953,14 @@ network_addr_match(const char *a, const char *b, const char *mask)
#endif
/*
+ * AIX 7.1 treats the empty string as equivalent to 0.0.0.0 and allows it
+ * to match, but it's too easy to get the empty string from some sort of
+ * syntax error. Special-case the empty string to always return false.
+ */
+ if (a[0] == '\0' || b[0] == '\0')
+ return false;
+
+ /*
* If the addresses are IPv4, the mask may be in one of two forms. It can
* either be a traditional mask, like 255.255.0.0, or it can be a CIDR
* subnet designation, like 16. (The caller should have already removed
diff --git a/util/network.h b/util/network.h
index c9b26ce..6532018 100644
--- a/util/network.h
+++ b/util/network.h
@@ -5,6 +5,7 @@
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
* Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2014 Russ Allbery <eagle@eyrie.org>
* Copyright 2009, 2010, 2011, 2012, 2013
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2010
@@ -45,9 +46,9 @@ BEGIN_DECLS
/*
* Create a socket of the given type and bind it to the specified address and
- * port (either IPv4 or IPv6), returning the resulting file descriptor or -1
- * on error. Errors are reported using warn/syswarn. To bind to all
- * interfaces, use "any" or "all" for address.
+ * port (either IPv4 or IPv6), returning the resulting file descriptor or
+ * INVALID_SOCKET on error. Errors are reported using warn/syswarn. To bind
+ * to all interfaces, use "any" or "all" for address.
*/
socket_type network_bind_ipv4(int type, const char *addr, unsigned short port)
__attribute__((__nonnull__));
@@ -73,7 +74,7 @@ void network_bind_all_free(socket_type *fds);
/*
* Wait on an array of file descriptor for one of them to select ready for
* read, and return the first file descriptor that does so. This is primarily
- * intended for UDP services listening on mutliple file descriptors. TCP
+ * intended for UDP services listening on multiple file descriptors. TCP
* services will probably want to use network_accept_any instead.
*
* This is not intended to be a replacement for a full event loop, just some
@@ -97,8 +98,10 @@ socket_type network_accept_any(socket_type fds[], unsigned int count,
/*
* Create a socket and connect it to the remote service given by the linked
* list of addrinfo structs. Returns the new file descriptor on success and
- * -1 on failure, with the error left in errno. Takes an optional source
- * address and a timeout in seconds, which may be 0 for no timeout.
+ * INVALID_SOCKET on failure, with the error left in errno. Takes an optional
+ * source address and a timeout in seconds, which may be 0 for no timeout.
+ * (Source may also be "all" or "any", which mean the same thing as NULL: do
+ * not use any particular source address.)
*/
socket_type network_connect(const struct addrinfo *, const char *source,
time_t)
@@ -115,8 +118,8 @@ socket_type network_connect_host(const char *host, unsigned short port,
/*
* Creates a socket of the specified domain and type and binds it to the
* appropriate source address, either the one supplied or all addresses if the
- * source address is NULL or "all". Returns the newly created file descriptor
- * or -1 on error.
+ * source address is NULL, "all", or "any". Returns the newly created file
+ * descriptor or INVALID_SOCKET on error.
*
* This is a lower-level function intended primarily for the use of clients
* that will then go on to do a non-blocking connect.
diff --git a/util/vector.c b/util/vector.c
index 21ee94e..1c1677f 100644
--- a/util/vector.c
+++ b/util/vector.c
@@ -70,9 +70,9 @@ cvector_new(void)
/*
- * Resize a vector (using realloc to resize the table). Maintain a minimum
- * allocated size of 1 so that the strings data element is never NULL. This
- * simplifies other code.
+ * Resize a vector (using reallocarray to resize the table). Maintain a
+ * minimum allocated size of 1 so that the strings data element is never NULL.
+ * This simplifies other code.
*/
void
vector_resize(struct vector *vector, size_t size)
@@ -457,10 +457,10 @@ cvector_split_space(char *string, struct cvector *vector)
/*
* Given a vector and a separator string, allocate and build a new string
* composed of all the strings in the vector separated from each other by the
- * seperator string. Caller is responsible for freeing.
+ * separator string. Caller is responsible for freeing.
*/
char *
-vector_join(const struct vector *vector, const char *seperator)
+vector_join(const struct vector *vector, const char *separator)
{
char *string;
size_t i, size, seplen;
@@ -470,24 +470,30 @@ vector_join(const struct vector *vector, const char *seperator)
if (vector->count == 0)
return xstrdup("");
- /* Determine the total size of the resulting string. */
- seplen = strlen(seperator);
- for (size = 0, i = 0; i < vector->count; i++)
+ /*
+ * Determine the total size of the resulting string. Be careful of
+ * integer overflow while doing so.
+ */
+ seplen = strlen(separator);
+ for (size = 0, i = 0; i < vector->count; i++) {
+ assert(SIZE_MAX - size >= strlen(vector->strings[i]) + seplen + 1);
size += strlen(vector->strings[i]);
+ }
+ assert(SIZE_MAX - size >= (vector->count - 1) * seplen + 1);
size += (vector->count - 1) * seplen + 1;
/* Allocate the memory and build up the string using strlcat. */
string = xmalloc(size);
strlcpy(string, vector->strings[0], size);
for (i = 1; i < vector->count; i++) {
- strlcat(string, seperator, size);
+ strlcat(string, separator, size);
strlcat(string, vector->strings[i], size);
}
return string;
}
char *
-cvector_join(const struct cvector *vector, const char *seperator)
+cvector_join(const struct cvector *vector, const char *separator)
{
char *string;
size_t i, size, seplen;
@@ -497,17 +503,23 @@ cvector_join(const struct cvector *vector, const char *seperator)
if (vector->count == 0)
return xstrdup("");
- /* Determine the total size of the resulting string. */
- seplen = strlen(seperator);
- for (size = 0, i = 0; i < vector->count; i++)
+ /*
+ * Determine the total size of the resulting string. Be careful of
+ * integer overflow while doing so.
+ */
+ seplen = strlen(separator);
+ for (size = 0, i = 0; i < vector->count; i++) {
+ assert(SIZE_MAX - size >= strlen(vector->strings[i]));
size += strlen(vector->strings[i]);
+ }
+ assert(SIZE_MAX - size >= (vector->count - 1) * seplen + 1);
size += (vector->count - 1) * seplen + 1;
/* Allocate the memory and build up the string using strlcat. */
string = xmalloc(size);
strlcpy(string, vector->strings[0], size);
for (i = 1; i < vector->count; i++) {
- strlcat(string, seperator, size);
+ strlcat(string, separator, size);
strlcat(string, vector->strings[i], size);
}
return string;
diff --git a/util/vector.h b/util/vector.h
index 85be6b1..844b07f 100644
--- a/util/vector.h
+++ b/util/vector.h
@@ -125,7 +125,7 @@ struct cvector *cvector_split_space(char *string, struct cvector *)
* specified string as separator. Returns a newly allocated string; caller is
* responsible for freeing.
*/
-char *vector_join(const struct vector *, const char *seperator)
+char *vector_join(const struct vector *, const char *separator)
__attribute__((__malloc__, __nonnull__, __warn_unused_result__));
char *cvector_join(const struct cvector *, const char *separator)
__attribute__((__malloc__, __nonnull__, __warn_unused_result__));
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 721447a..4af8ee9 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -258,6 +258,7 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
}
+ va_end(args);
}
#else /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
void
@@ -280,5 +281,6 @@ x_asprintf(char **strp, const char *fmt, ...)
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
}
+ va_end(args);
}
#endif /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
diff --git a/util/xmalloc.h b/util/xmalloc.h
index a4b4686..6aa9b93 100644
--- a/util/xmalloc.h
+++ b/util/xmalloc.h
@@ -90,7 +90,7 @@ char *x_strdup(const char *, const char *, int)
char *x_strndup(const char *, size_t, const char *, int)
__attribute__((__malloc__, __nonnull__));
void x_vasprintf(char **, const char *, va_list, const char *, int)
- __attribute__((__nonnull__));
+ __attribute__((__nonnull__, __format__(printf, 2, 0)));
/* asprintf special case. */
#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
diff --git a/util/xwrite.c b/util/xwrite.c
index 562bd27..eb143cd 100644
--- a/util/xwrite.c
+++ b/util/xwrite.c
@@ -58,11 +58,14 @@
/*
* If we're running the test suite, call testing versions of the write
- * functions. #undef pwrite first because large file support may define a
- * macro pwrite (pointing to pwrite64) on some platforms (e.g. Solaris).
+ * functions. #undef the functions first since large file support may define
+ * a macro pwrite (pointing to pwrite64) on some platforms (e.g. Solaris),
+ * and it's possible the other functions may be similarly affected.
*/
#if TESTING
# undef pwrite
+# undef write
+# undef writev
# define pwrite fake_pwrite
# define write fake_write
# define writev fake_writev
@@ -77,7 +80,7 @@ xwrite(int fd, const void *buffer, size_t size)
{
size_t total;
ssize_t status;
- int count = 0;
+ unsigned int count = 0;
if (size == 0)
return 0;
@@ -105,7 +108,7 @@ xpwrite(int fd, const void *buffer, size_t size, off_t offset)
{
size_t total;
ssize_t status;
- int count = 0;
+ unsigned int count = 0;
if (size == 0)
return 0;
@@ -134,7 +137,7 @@ xwritev(int fd, const struct iovec iov[], int iovcnt)
{
ssize_t total, status = 0;
size_t left, offset;
- int iovleft, i, count;
+ unsigned int iovleft, i, count;
struct iovec *tmpiov;
/*
@@ -150,7 +153,7 @@ xwritev(int fd, const struct iovec iov[], int iovcnt)
}
/* Get a count of the total number of bytes in the iov array. */
- for (total = 0, i = 0; i < iovcnt; i++)
+ for (total = 0, i = 0; i < (unsigned int) iovcnt; i++)
total += iov[i].iov_len;
if (total == 0)
return 0;
diff --git a/util/xwrite.h b/util/xwrite.h
index 203eaba..8ca4485 100644
--- a/util/xwrite.h
+++ b/util/xwrite.h
@@ -33,7 +33,7 @@
#include <config.h>
#include <portable/macros.h>
-#include <stddef.h>
+#include <sys/types.h>
/* Forward declaration to avoid an include. */
struct iovec;