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