Index: squid-3.1.23/tools/cachemgr.cc
===================================================================
--- squid-3.1.23.orig/tools/cachemgr.cc
+++ squid-3.1.23/tools/cachemgr.cc
@@ -33,6 +33,7 @@
 #include "config.h"
 #include "getfullhostname.h"
 #include "ip/IpAddress.h"
+#include "MemBuf.h"
 #include "rfc1738.h"
 #include "util.h"
 
@@ -155,6 +156,7 @@ typedef struct {
 
 /* debugging level 0 (disabled) - 3 (max) */
 #define DEBUG_LEVEL 0
+#undef debug // defined in MemBuf.h and we want our own
 #define debug(level) if ((level) <= DEBUG_LEVEL && DEBUG_LEVEL > 0)
 
 /*
@@ -168,6 +170,7 @@ static time_t now;
 /*
  * Function prototypes
  */
+#undef safe_free // defined in MemBuf.h and we want our own ...
 #define safe_free(str) { if (str) { xfree(str); (str) = NULL; } }
 static const char *safe_str(const char *str);
 static const char *xstrtok(char **str, char del);
@@ -452,8 +455,8 @@ menu_url(cachemgr_request * req, const c
     return url;
 }
 
-static const char *
-munge_menu_line(const char *buf, cachemgr_request * req)
+static void
+munge_menu_line(MemBuf &out, const char *buf, cachemgr_request * req)
 {
     char *x;
     const char *a;
@@ -461,15 +464,14 @@ munge_menu_line(const char *buf, cachemg
     const char *p;
     char *a_url;
     char *buf_copy;
-    static char html[2 * 1024];
 
-    if (strlen(buf) < 1)
-        return buf;
-
-    if (*buf != ' ')
-        return buf;
+    const char bufLen = strlen(buf);
+    if (bufLen < 1 || *buf != ' ') {
+        out.append(buf, bufLen);
+        return;
+    }
 
-    buf_copy = x = xstrdup(buf);
+    buf_copy = x = xstrndup(buf, bufLen);
 
     a = xstrtok(&x, '\t');
 
@@ -481,59 +483,59 @@ munge_menu_line(const char *buf, cachemg
 
     /* no reason to give a url for a disabled action */
     if (!strcmp(p, "disabled"))
-        snprintf(html, sizeof(html), "<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\n", d, a_url);
-    else
+        out.Printf("<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\n", d, a_url);
+    else {
         /* disable a hidden action (requires a password, but password is not in squid.conf) */
-        if (!strcmp(p, "hidden"))
-            snprintf(html, sizeof(html), "<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d, a_url);
-        else
+        if (!strcmp(p, "hidden")) {
+            out.Printf("<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d, a_url);
+        }
+        else {
             /* disable link if authentication is required and we have no password */
-            if (!strcmp(p, "protected") && !req->passwd)
-                snprintf(html, sizeof(html), "<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
-                         d, menu_url(req, "authenticate"), a_url);
-            else
-                /* highlight protected but probably available entries */
+            if (!strcmp(p, "protected") && !req->passwd) {
+                out.Printf("<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
+                           d, menu_url(req, "authenticate"), a_url);
+            }
+            else {
                 if (!strcmp(p, "protected"))
-                    snprintf(html, sizeof(html), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n",
-                             a_url, d);
-
-    /* public entry or unknown type of protection */
+                    /* highlight protected but probably available entries */
+                    out.Printf("<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n", a_url, d);
+                /* public entry or unknown type of protection */
                 else
-                    snprintf(html, sizeof(html), "<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url, d);
+                    out.Printf("<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url, d);
+            }
+        }
+    }
 
     xfree(a_url);
 
     xfree(buf_copy);
-
-    return html;
 }
 
-static const char *
-munge_other_line(const char *buf, cachemgr_request * req)
+static void
+munge_other_line(MemBuf &out, const char *buf, cachemgr_request *)
 {
     static const char *ttags[] = {"td", "th"};
 
-    static char html[4096];
     static int table_line_num = 0;
     static int next_is_header = 0;
     int is_header = 0;
     const char *ttag;
     char *buf_copy;
     char *x, *p;
-    int l = 0;
     /* does it look like a table? */
 
     if (!strchr(buf, '\t') || *buf == '\t') {
         /* nope, just text */
-        snprintf(html, sizeof(html), "%s%s",
-                 table_line_num ? "</table>\n<pre>" : "", html_quote(buf));
+        if (table_line_num)
+            out.append("</table>\n<pre>", 14);
+        out.Printf("%s", html_quote(buf));
         table_line_num = 0;
-        return html;
+        return;
     }
 
     /* start html table */
     if (!table_line_num) {
-        l += snprintf(html + l, sizeof(html) - l, "</pre><table cellpadding=\"2\" cellspacing=\"1\">\n");
+        out.append("</pre><table cellpadding=\"2\" cellspacing=\"1\">\n", 46);
         next_is_header = 0;
     }
 
@@ -543,7 +545,7 @@ munge_other_line(const char *buf, cachem
     ttag = ttags[is_header];
 
     /* record starts */
-    l += snprintf(html + l, sizeof(html) - l, "<tr>");
+    out.append("<tr>", 4);
 
     /* substitute '\t' */
     buf_copy = x = xstrdup(buf);
@@ -560,7 +562,7 @@ munge_other_line(const char *buf, cachem
             x++;
         }
 
-        l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s</%s>",
+        out.Printf("<%s colspan=\"%d\" align=\"%s\">%s</%s>",
                       ttag, column_span,
                       is_header ? "center" : is_number(cell) ? "right" : "left",
                       html_quote(cell), ttag);
@@ -568,10 +570,9 @@ munge_other_line(const char *buf, cachem
 
     xfree(buf_copy);
     /* record ends */
-    snprintf(html + l, sizeof(html) - l, "</tr>\n");
+    out.append("</tr>\n", 6);
     next_is_header = is_header && strstr(buf, "\t\t");
     table_line_num++;
-    return html;
 }
 
 static const char *
@@ -728,14 +729,19 @@ read_reply(int s, cachemgr_request * req
             /* yes, fall through, we do not want to loose the first line */
 
         case isBody:
+        {
             /* interpret [and reformat] cache response */
+            MemBuf out;
+            out.init();
 
             if (parse_menu)
-                fputs(munge_menu_line(buf, req), stdout);
+                munge_menu_line(out, buf, req);
             else
-                fputs(munge_other_line(buf, req), stdout);
+                munge_other_line(out, buf, req);
 
-            break;
+            fputs(out.buf, stdout);
+        }
+        break;
 
         case isForward:
             /* forward: no modifications allowed */
@@ -1000,7 +1006,7 @@ read_request(void)
     if (strlen(buf) == 0)
 #endif
     {
-        free(buf);
+        xfree(buf);
         return NULL;
     }
 
Index: squid-3.1.23/tools/Makefile.am
===================================================================
--- squid-3.1.23.orig/tools/Makefile.am
+++ squid-3.1.23/tools/Makefile.am
@@ -15,13 +15,16 @@ INCLUDES += -I$(srcdir)
 stub_debug.cc: $(top_srcdir)/src/stub_debug.cc
 	cp $(top_srcdir)/src/stub_debug.cc .
 
+MemBuf.cc: $(top_srcdir)/src/MemBuf.cc
+	cp $(top_srcdir)/src/MemBuf.cc $@
+
 ##  src/time.cc provides a usable time API.
 time.cc: $(top_srcdir)/src/time.cc
 	cp $(top_srcdir)/src/time.cc .
 
 # Neither of these should be disted from here.
 TESTSOURCES= stub_debug.cc time.cc
-CLEANFILES += stub_debug.cc time.cc
+CLEANFILES += stub_debug.cc MemBuf.cc time.cc
 
 SUBDIRS		= 
 
@@ -39,7 +42,7 @@ DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/
 squidclient_SOURCES = squidclient.cc
 nodist_squidclient_SOURCES=time.cc stub_debug.cc
 
-cachemgr__CGIEXT__SOURCES = cachemgr.cc
+cachemgr__CGIEXT__SOURCES = cachemgr.cc MemBuf.cc tools_mem.cc
 nodist_cachemgr__CGIEXT__SOURCES = time.cc stub_debug.cc
 cachemgr__CGIEXT__CXXFLAGS = -DDEFAULT_CACHEMGR_CONFIG=\"$(DEFAULT_CACHEMGR_CONFIG)\" $(AM_CXXFLAGS)
 
Index: squid-3.1.23/tools/tools_mem.cc
===================================================================
--- /dev/null
+++ squid-3.1.23/tools/tools_mem.cc
@@ -0,0 +1,58 @@
+#include "squid.h"
+#include "Mem.h"
+
+void
+memFreeString(size_t size, void *buf)
+{
+    xfree(buf);
+}
+
+void *
+memAllocString(size_t net_size, size_t * gross_size)
+{
+    *gross_size=net_size;
+    return xmalloc(net_size);
+}
+
+void
+memFreeBuf(size_t size, void *buf)
+{
+    xfree(buf);
+}
+
+void *
+memAllocBuf(size_t net_size, size_t * gross_size)
+{
+    *gross_size=net_size;
+    return xcalloc(1, net_size);
+}
+
+/* net_size is the new size, *gross size is the old gross size, to be changed to
+ * the new gross size as a side-effect.
+ */
+void *
+memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size)
+{
+    void *rv=xrealloc(oldbuf,net_size);
+//    if (net_size > *gross_size)
+//        memset(rv+net_size,0,net_size-*gross_size);
+    *gross_size=net_size;
+    return rv;
+}
+
+static void
+cxx_xfree(void * ptr)
+{
+    xfree(ptr);
+}
+
+FREE *
+memFreeBufFunc(size_t size)
+{
+    return cxx_xfree;
+}
+
+
+//void * memAllocate(mem_type type) STUB_RETVAL(NULL)
+//void memFree(void *p, int type) STUB
+
