diff -rNU 30 ../squid-3.1.12-o/tools/cachemgr.cc ./tools/cachemgr.cc
--- ../squid-3.1.12-o/tools/cachemgr.cc	2011-04-04 03:24:06.000000000 +0200
+++ ./tools/cachemgr.cc	2013-02-06 15:11:54.000000000 +0100
@@ -559,66 +559,69 @@
             column_span++;
             x++;
         }
 
         l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s</%s>",
                       ttag, column_span,
                       is_header ? "center" : is_number(cell) ? "right" : "left",
                       html_quote(cell), ttag);
     }
 
     xfree(buf_copy);
     /* record ends */
     snprintf(html + l, sizeof(html) - l, "</tr>\n");
     next_is_header = is_header && strstr(buf, "\t\t");
     table_line_num++;
     return html;
 }
 
 static const char *
 munge_action_line(const char *_buf, cachemgr_request * req)
 {
     static char html[2 * 1024];
     char *buf = xstrdup(_buf);
     char *x = buf;
     const char *action, *description;
     char *p;
 
     if ((p = strchr(x, '\n')))
         *p = '\0';
     action = xstrtok(&x, '\t');
+    if (!action) {
+	xfree(buf);
+	return "";
+    }
     description = xstrtok(&x, '\t');
     if (!description)
         description = action;
-    if (!action)
-        return "";
     snprintf(html, sizeof(html), " <a href=\"%s\">%s</a>", menu_url(req, action), description);
+    xfree(buf);
     return html;
 }
 
 static int
 read_reply(int s, cachemgr_request * req)
 {
     char buf[4 * 1024];
 #ifdef _SQUID_MSWIN_
 
     int reply;
     char *tmpfile = tempnam(NULL, "tmp0000");
     FILE *fp = fopen(tmpfile, "w+");
 #else
 
     FILE *fp = fdopen(s, "r");
 #endif
     /* interpretation states */
     enum {
         isStatusLine, isHeaders, isActions, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError
     } istate = isStatusLine;
     int parse_menu = 0;
     const char *action = req->action;
     const char *statusStr = NULL;
     int status = -1;
 
     if (0 == strlen(req->action))
         parse_menu = 1;
     else if (0 == strcasecmp(req->action, "menu"))
         parse_menu = 1;
 
@@ -793,176 +796,198 @@
     struct addrinfo *AI = NULL;
     IpAddress S;
     int s;
     int l;
 
     static char buf[2 * 1024];
 
     if (req == NULL) {
         auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, "");
         return 1;
     }
 
     if (req->hostname == NULL) {
         req->hostname = xstrdup(CACHEMGR_HOSTNAME);
     }
 
     if (req->port == 0) {
         req->port = CACHE_HTTP_PORT;
     }
 
     if (req->action == NULL) {
         req->action = xstrdup("");
     }
 
     if (strcmp(req->action, "authenticate") == 0) {
         auth_html(req->hostname, req->port, req->user_name);
         return 0;
     }
 
     if (!check_target_acl(req->hostname, req->port)) {
-        snprintf(buf, 1024, "target %s:%d not allowed in cachemgr.conf\n", req->hostname, req->port);
+        snprintf(buf, sizeof(buf), "target %s:%d not allowed in cachemgr.conf\n", req->hostname, req->port);
         error_html(buf);
         return 1;
     }
 
     S = *gethostbyname(req->hostname);
 
     if ( !S.IsAnyAddr() ) {
         (void) 0;
     } else if ((S = req->hostname))
         (void) 0;
     else {
-        snprintf(buf, 1024, "Unknown host: %s\n", req->hostname);
+        snprintf(buf, sizeof(buf), "Unknown host: %s\n", req->hostname);
         error_html(buf);
         return 1;
     }
 
     S.SetPort(req->port);
 
     S.GetAddrInfo(AI);
 
 #if USE_IPV6
     if ((s = socket( AI->ai_family, SOCK_STREAM, 0)) < 0) {
 #else
     if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
 #endif
-        snprintf(buf, 1024, "socket: %s\n", xstrerror());
+        snprintf(buf, sizeof(buf), "socket: %s\n", xstrerror());
         error_html(buf);
+	S.FreeAddrInfo(AI);
         return 1;
     }
 
     if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) {
-        snprintf(buf, 1024, "connect %s: %s\n",
+        snprintf(buf, sizeof(buf), "connect %s: %s\n",
                  S.ToURL(ipbuf,MAX_IPSTRLEN),
                  xstrerror());
         error_html(buf);
         S.FreeAddrInfo(AI);
+	close(s);
         return 1;
     }
 
     S.FreeAddrInfo(AI);
 
     l = snprintf(buf, sizeof(buf),
                  "GET cache_object://%s/%s HTTP/1.0\r\n"
                  "Accept: */*\r\n"
                  "%s"			/* Authentication info or nothing */
                  "\r\n",
                  req->hostname,
                  req->action,
                  make_auth_header(req));
     if (write(s, buf, l) < 0) {
         debug(1) fprintf(stderr, "ERROR: (%d) writing request: '%s'\n", errno, buf);
     } else {
         debug(1) fprintf(stderr, "wrote request: '%s'\n", buf);
     }
     return read_reply(s, req);
 }
 
 int
 main(int argc, char *argv[])
 {
     char *s;
     cachemgr_request *req;
 
     now = time(NULL);
 #ifdef _SQUID_MSWIN_
 
     Win32SockInit();
     atexit(Win32SockCleanup);
     _setmode( _fileno( stdin ), _O_BINARY );
     _setmode( _fileno( stdout ), _O_BINARY );
     _fmode = _O_BINARY;
 
     if ((s = strrchr(argv[0], '\\')))
 #else
 
     if ((s = strrchr(argv[0], '/')))
 #endif
 
         progname = xstrdup(s + 1);
     else
         progname = xstrdup(argv[0]);
 
     if ((s = getenv("SCRIPT_NAME")) != NULL)
         script_name = xstrdup(s);
 
     req = read_request();
 
     return process_request(req);
 }
 
 static char *
 read_post_request(void)
 {
     char *s;
-    char *buf;
-    int len;
 
     if ((s = getenv("REQUEST_METHOD")) == NULL)
         return NULL;
 
     if (0 != strcasecmp(s, "POST"))
         return NULL;
 
     if ((s = getenv("CONTENT_LENGTH")) == NULL)
         return NULL;
 
-    if ((len = atoi(s)) <= 0)
+    if (*s == '-') // negative length content huh?
         return NULL;
 
-    buf = (char *)xmalloc(len + 1);
+    uint64_t len;
 
-    if (fread(buf, len, 1, stdin) == 0)
+    char *endptr = s+ strlen(s);
+    if ((len = strtoll(s, &endptr, 10)) <= 0)
         return NULL;
 
-    buf[len] = '\0';
+    // limit the input to something reasonable.
+    // 4KB should be enough for the GET/POST data length, but may be extended.
+    if (len >= 4096) {
+	printf("Status: 400 Bad Request\n\n");
+	exit(0);
+    }
+    char *buf = (char *)xmalloc(len + 1);
+
+    size_t readLen = fread(buf, 1, len, stdin);
+    if (readLen == 0) {
+        xfree(buf);
+        return NULL;
+    }
+    buf[readLen] = '\0';
+    len -= readLen;
+
+    // purge the remainder of the request entity
+    while (len > 0 && readLen) {
+        char temp[65535];
+        readLen = fread(temp, 1, 65535, stdin);
+        len -= readLen;
+    }
 
     return buf;
 }
 
 static char *
 read_get_request(void)
 {
     char *s;
 
     if ((s = getenv("QUERY_STRING")) == NULL)
         return NULL;
 
     return xstrdup(s);
 }
 
 static cachemgr_request *
 read_request(void)
 {
     char *buf;
 
     cachemgr_request *req;
     char *s;
     char *t;
     char *q;
 
     if ((buf = read_post_request()) != NULL)
         (void) 0;
     else if ((buf = read_get_request()) != NULL)
         (void) 0;
     else
@@ -1048,128 +1073,141 @@
              req->user_name ? req->user_name : "",
              req->passwd);
 
     debug(3) fprintf(stderr, "cmgr: pre-encoded for pub: %s\n", buf);
 
     debug(3) fprintf(stderr, "cmgr: encoded: '%s'\n", base64_encode(buf));
 
     req->pub_auth = xstrdup(base64_encode(buf));
 }
 
 static void
 decode_pub_auth(cachemgr_request * req)
 {
     char *buf;
     const char *host_name;
     const char *time_str;
     const char *user_name;
     const char *passwd;
 
     debug(2) fprintf(stderr, "cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth));
     safe_free(req->passwd);
 
     if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname)))
         return;
 
     buf = xstrdup(base64_decode(req->pub_auth));
 
     debug(3) fprintf(stderr, "cmgr: length ok\n");
 
     /* parse ( a lot of memory leaks, but that is cachemgr style :) */
-    if ((host_name = strtok(buf, "|")) == NULL)
+    if ((host_name = strtok(buf, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug(3) fprintf(stderr, "cmgr: decoded host: '%s'\n", host_name);
 
-    if ((time_str = strtok(NULL, "|")) == NULL)
+    if ((time_str = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug(3) fprintf(stderr, "cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now);
 
-    if ((user_name = strtok(NULL, "|")) == NULL)
+    if ((user_name = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug(3) fprintf(stderr, "cmgr: decoded uname: '%s'\n", user_name);
 
-    if ((passwd = strtok(NULL, "|")) == NULL)
+    if ((passwd = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug(2) fprintf(stderr, "cmgr: decoded passwd: '%s'\n", passwd);
 
     /* verify freshness and validity */
-    if (atoi(time_str) + passwd_ttl < now)
+    if (atoi(time_str) + passwd_ttl < now) {
+        xfree(buf);
         return;
+    }
 
-    if (strcasecmp(host_name, req->hostname))
+    if (strcasecmp(host_name, req->hostname)) {
+        xfree(buf);
         return;
+    }
 
     debug(1) fprintf(stderr, "cmgr: verified auth. info.\n");
 
     /* ok, accept */
-    xfree(req->user_name);
+    safe_free(req->user_name);
 
     req->user_name = xstrdup(user_name);
 
     req->passwd = xstrdup(passwd);
 
     xfree(buf);
 }
 
 static void
 reset_auth(cachemgr_request * req)
 {
     safe_free(req->passwd);
     safe_free(req->pub_auth);
 }
 
 static const char *
 make_auth_header(const cachemgr_request * req)
 {
     static char buf[1024];
     size_t stringLength = 0;
     const char *str64;
 
     if (!req->passwd)
         return "";
 
     snprintf(buf, sizeof(buf), "%s:%s",
              req->user_name ? req->user_name : "",
              req->passwd);
 
     str64 = base64_encode(buf);
 
     stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64);
 
     assert(stringLength < sizeof(buf));
 
     snprintf(&buf[stringLength], sizeof(buf) - stringLength, "Proxy-Authorization: Basic %s\r\n", str64);
 
+    xxfree(str64);
     return buf;
 }
 
 static int
 check_target_acl(const char *hostname, int port)
 {
     char config_line[BUFSIZ];
     FILE *fp = NULL;
     int ret = 0;
     fp = fopen("cachemgr.conf", "r");
 
     if (fp == NULL)
         fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
 
     if (fp == NULL) {
 #ifdef CACHEMGR_HOSTNAME_DEFINED
 
         if (strcmp(hostname, CACHEMGR_HOSTNAME) == 0 && port == CACHE_HTTP_PORT)
             return 1;
 
 #else
 
         if (strcmp(hostname, "localhost") == 0)
             return 1;
 
         if (strcmp(hostname, getfullhostname()) == 0)
             return 1;
 
 #endif
 
