diff options
author | Russ Allbery <eagle@eyrie.org> | 2015-09-04 22:21:31 -0700 |
---|---|---|
committer | Russ Allbery <eagle@eyrie.org> | 2015-09-04 22:21:31 -0700 |
commit | f74ab497a7489d7b0bf1f517d72bbd0e7d382031 (patch) | |
tree | 1f78c15afdb729aff58cf1543fa5cbf80bc9bc9f /util | |
parent | 1899f8815bd606790b8e88a6a43651cac911166e (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.c | 7 | ||||
-rw-r--r-- | util/macros.h | 4 | ||||
-rw-r--r-- | util/messages.c | 2 | ||||
-rw-r--r-- | util/messages.h | 19 | ||||
-rw-r--r-- | util/network.c | 46 | ||||
-rw-r--r-- | util/network.h | 19 | ||||
-rw-r--r-- | util/vector.c | 40 | ||||
-rw-r--r-- | util/vector.h | 2 | ||||
-rw-r--r-- | util/xmalloc.c | 2 | ||||
-rw-r--r-- | util/xmalloc.h | 2 | ||||
-rw-r--r-- | util/xwrite.c | 15 | ||||
-rw-r--r-- | util/xwrite.h | 2 |
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; |