--- apr-1.2.7/test/testsock.c.psprintfpi +++ apr-1.2.7/test/testsock.c @@ -207,6 +207,29 @@ APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); } +static void test_print_addr(abts_case *tc, void *data) +{ + apr_sockaddr_t *sa; + char *s; + + APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", + apr_sockaddr_info_get(&sa, "0.0.0.0", APR_INET, 80, 0, p)); + + s = apr_psprintf(p, "foo %pI bar", sa); + + ABTS_STR_EQUAL(tc, "foo 0.0.0.0:80 bar", s); + +#if APR_HAVE_IPV6 + if (apr_sockaddr_info_get(&sa, "::ffff:0.0.0.0", APR_INET6, 80, 0, p) == APR_SUCCESS) { + /* sa should now be a v4-mapped IPv6 address. */ + + s = apr_psprintf(p, "%pI", sa); + + ABTS_STR_EQUAL(tc, "0.0.0.0:80", s); + } +#endif +} + static void test_get_addr(abts_case *tc, void *data) { apr_status_t rv; @@ -284,6 +307,7 @@ abts_run_test(suite, test_send, NULL); abts_run_test(suite, test_recv, NULL); abts_run_test(suite, test_timeout, NULL); + abts_run_test(suite, test_print_addr, NULL); abts_run_test(suite, test_get_addr, NULL); return suite; --- apr-1.2.7/strings/apr_snprintf.c.psprintfpi +++ apr-1.2.7/strings/apr_snprintf.c @@ -463,7 +463,8 @@ } - +/* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points + * to 1 byte past the end of the buffer. */ static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len) { char *p = buf_end; @@ -473,7 +474,14 @@ p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len); *--p = ':'; - apr_sockaddr_ip_get(&ipaddr_str, sa); + ipaddr_str = buf_end - NUM_BUF_SIZE; + if (apr__sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) { + /* Should only fail if the buffer is too small, which it + * should not be; but fail safe anyway: */ + *--p = '?'; + *len = buf_end - p; + return p; + } sub_len = strlen(ipaddr_str); #if APR_HAVE_IPV6 if (sa->family == APR_INET6 && --- apr-1.2.7/include/arch/apr_private_common.h.psprintfpi +++ apr-1.2.7/include/arch/apr_private_common.h @@ -23,6 +23,7 @@ #include "apr_pools.h" #include "apr_tables.h" +#include "apr_network_io.h" apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, const char *liststr, @@ -34,6 +35,13 @@ char separator, apr_pool_t *p); +/* This is a non-allocating version of apr_sockaddr_ip_get() which is + * used internally (in 1.2.x) by the vformatter implementation. + * Writes the address to @param buf which is of length @buflen. + */ +apr_status_t apr__sockaddr_ip_getbuf(char *buf, apr_size_t buflen, + apr_sockaddr_t *sockaddr); + /* temporary defines to handle 64bit compile mismatches */ #define APR_INT_TRUNC_CAST int #define APR_UINT32_TRUNC_CAST apr_uint32_t --- apr-1.2.7/network_io/unix/sockaddr.c.psprintfpi +++ apr-1.2.7/network_io/unix/sockaddr.c @@ -98,27 +98,37 @@ } } -APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, - apr_sockaddr_t *sockaddr) +apr_status_t apr__sockaddr_ip_getbuf(char *buf, apr_size_t buflen, + apr_sockaddr_t *sockaddr) { - *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len); - apr_inet_ntop(sockaddr->family, - sockaddr->ipaddr_ptr, - *addr, - sockaddr->addr_str_len); + if (!apr_inet_ntop(sockaddr->family, sockaddr->ipaddr_ptr, buf, buflen)) { + return APR_ENOSPC; + } + #if APR_HAVE_IPV6 - if (sockaddr->family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)) { + if (sockaddr->family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr) + && buflen > strlen("::ffff:")) { /* This is an IPv4-mapped IPv6 address; drop the leading * part of the address string so we're left with the familiar * IPv4 format. */ - *addr += strlen("::ffff:"); + memmove(buf, buf + strlen("::ffff:"), + strlen(buf + strlen("::ffff:"))+1); } #endif + /* ensure NUL termination if the buffer is too short */ + buf[buflen-1] = '\0'; return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr) +{ + *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len); + return apr__sockaddr_ip_getbuf(*addr, sockaddr->addr_str_len, sockaddr); +} + void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port) { addr->family = family;