diff -u -r -N squid-3.1.21/ChangeLog squid-3.1.22/ChangeLog
--- squid-3.1.21/ChangeLog	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/ChangeLog	2012-12-02 23:02:17.000000000 +1300
@@ -1,3 +1,11 @@
+Changes to squid-3.1.22 (03 Dec 2012):
+
+	- Bug 3685: Squid hangs in Delay Pools ClassCBucket::update
+	- Bug 3659: read_timeout problem with HTTPS
+	- Bug 3654: Fix IPv6 enabled squidclient
+	- Bug 3189: AIO thread race on pipe() initialization
+	- cachemgr.cgi: Memory Leaks and DoS Vulnerability
+
 Changes to squid-3.1.21 (23 Sep 2012):
 
 	- Bug 3622: peerClearRRStart scheduling multiple events
diff -u -r -N squid-3.1.21/configure squid-3.1.22/configure
--- squid-3.1.21/configure	2012-09-24 02:02:46.000000000 +1200
+++ squid-3.1.22/configure	2012-12-02 23:03:29.000000000 +1300
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for Squid Web Proxy 3.1.21.
+# Generated by GNU Autoconf 2.68 for Squid Web Proxy 3.1.22.
 #
 # Report bugs to <http://www.squid-cache.org/bugs/>.
 #
@@ -575,8 +575,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='3.1.21'
-PACKAGE_STRING='Squid Web Proxy 3.1.21'
+PACKAGE_VERSION='3.1.22'
+PACKAGE_STRING='Squid Web Proxy 3.1.22'
 PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/'
 PACKAGE_URL=''
 
@@ -1540,7 +1540,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Squid Web Proxy 3.1.21 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 3.1.22 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1610,7 +1610,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 3.1.21:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 3.1.22:";;
    esac
   cat <<\_ACEOF
 
@@ -1941,7 +1941,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 3.1.21
+Squid Web Proxy configure 3.1.22
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2952,7 +2952,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Squid Web Proxy $as_me 3.1.21, which was
+It was created by Squid Web Proxy $as_me 3.1.22, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3771,7 +3771,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='3.1.21'
+ VERSION='3.1.22'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -28243,7 +28243,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Squid Web Proxy $as_me 3.1.21, which was
+This file was extended by Squid Web Proxy $as_me 3.1.22, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -28309,7 +28309,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Squid Web Proxy config.status 3.1.21
+Squid Web Proxy config.status 3.1.22
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-3.1.21/configure.ac squid-3.1.22/configure.ac
--- squid-3.1.21/configure.ac	2012-09-24 02:02:46.000000000 +1200
+++ squid-3.1.22/configure.ac	2012-12-02 23:03:29.000000000 +1300
@@ -2,7 +2,7 @@
 dnl
 dnl  $Id$
 dnl
-AC_INIT([Squid Web Proxy],[3.1.21],[http://www.squid-cache.org/bugs/],[squid])
+AC_INIT([Squid Web Proxy],[3.1.22],[http://www.squid-cache.org/bugs/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
diff -u -r -N squid-3.1.21/include/version.h squid-3.1.22/include/version.h
--- squid-3.1.21/include/version.h	2012-09-24 02:02:46.000000000 +1200
+++ squid-3.1.22/include/version.h	2012-12-02 23:03:29.000000000 +1300
@@ -9,7 +9,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1348408851
+#define SQUID_RELEASE_TIME 1354442534
 #endif
 
 #ifndef APP_SHORTNAME
diff -u -r -N squid-3.1.21/RELEASENOTES.html squid-3.1.22/RELEASENOTES.html
--- squid-3.1.21/RELEASENOTES.html	2012-09-24 02:25:29.000000000 +1200
+++ squid-3.1.22/RELEASENOTES.html	2012-12-02 23:23:45.000000000 +1300
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.66">
- <TITLE>Squid 3.1.21 release notes</TITLE>
+ <TITLE>Squid 3.1.22 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.1.21 release notes</H1>
+<H1>Squid 3.1.22 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -71,7 +71,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-3.1.21</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.1.22</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.1/">http://www.squid-cache.org/Versions/v3/3.1/</A> or the 
 <A HREF="http://www.squid-cache.org/Mirrors/http-mirrors.html">mirrors</A>.</P>
diff -u -r -N squid-3.1.21/src/comm.cc squid-3.1.22/src/comm.cc
--- squid-3.1.21/src/comm.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/comm.cc	2012-12-02 23:02:17.000000000 +1300
@@ -2362,19 +2362,23 @@
     fdc_table[fd].acceptNext();
 }
 
-void CommIO::Initialise()
+void
+CommIO::Initialize()
 {
+    if (CommIO::Initialized)
+        return;
+
     /* Initialize done pipe signal */
     int DonePipe[2];
     if (pipe(DonePipe)) {}
     DoneFD = DonePipe[1];
     DoneReadFD = DonePipe[0];
-    fd_open(DoneReadFD, FD_PIPE, "async-io completetion event: main");
-    fd_open(DoneFD, FD_PIPE, "async-io completetion event: threads");
+    fd_open(DoneReadFD, FD_PIPE, "async-io completion event: main");
+    fd_open(DoneFD, FD_PIPE, "async-io completion event: threads");
     commSetNonBlocking(DoneReadFD);
     commSetNonBlocking(DoneFD);
     commSetSelect(DoneReadFD, COMM_SELECT_READ, NULLFDHandler, NULL, 0);
-    Initialised = true;
+    Initialized = true;
 }
 
 void CommIO::NotifyIOClose()
@@ -2385,10 +2389,10 @@
     close(DoneReadFD);
     fd_close(DoneFD);
     fd_close(DoneReadFD);
-    Initialised = false;
+    Initialized = false;
 }
 
-bool CommIO::Initialised = false;
+bool CommIO::Initialized = false;
 bool CommIO::DoneSignalled = false;
 int CommIO::DoneFD = -1;
 int CommIO::DoneReadFD = -1;
diff -u -r -N squid-3.1.21/src/CommIO.h squid-3.1.22/src/CommIO.h
--- squid-3.1.21/src/CommIO.h	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/CommIO.h	2012-12-02 23:02:17.000000000 +1300
@@ -9,25 +9,25 @@
 public:
     static inline void NotifyIOCompleted();
     static void ResetNotifications();
-    static void Initialise();
+    static void Initialize();
     static void NotifyIOClose();
 
 private:
     static void NULLFDHandler(int, void *);
     static void FlushPipe();
-    static bool Initialised;
+    static bool Initialized;
     static bool DoneSignalled;
     static int DoneFD;
     static int DoneReadFD;
 };
 
-
-/* Inline code. TODO: make structued approach to inlining */
+/* Inline code. TODO: make structured approach to inlining */
 void
 CommIO::NotifyIOCompleted()
 {
-    if (!Initialised)
-        Initialise();
+    if (!Initialized) {
+        fatalf("Disk Threads I/O pipes not initialized before first use.");
+    }
 
     if (!DoneSignalled) {
         DoneSignalled = true;
diff -u -r -N squid-3.1.21/src/delay_pools.cc squid-3.1.22/src/delay_pools.cc
--- squid-3.1.21/src/delay_pools.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/delay_pools.cc	2012-12-02 23:02:17.000000000 +1300
@@ -366,7 +366,7 @@
     /* If we aren't active, don't try to update us ! */
     assert (rate.restore_bps != -1);
 
-    for (unsigned char j = 0; j < individuals.size(); ++j)
+    for (unsigned int j = 0; j < individuals.size(); ++j)
         individuals.values[j].update (rate, incr);
 }
 
diff -u -r -N squid-3.1.21/src/DiskIO/DiskThreads/aiops.cc squid-3.1.22/src/DiskIO/DiskThreads/aiops.cc
--- squid-3.1.21/src/DiskIO/DiskThreads/aiops.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/DiskIO/DiskThreads/aiops.cc	2012-12-02 23:02:17.000000000 +1300
@@ -309,6 +309,10 @@
 
     done_queue.blocked = 0;
 
+    // Initialize the thread I/O pipes before creating any threads
+    // see bug 3189 comment 5 about race conditions.
+    CommIO::Initialize();
+
     /* Create threads and get them to sit in their wait loop */
     squidaio_thread_pool = memPoolCreate("aio_thread", sizeof(squidaio_thread_t));
 
diff -u -r -N squid-3.1.21/src/tests/stub_CommIO.cc squid-3.1.22/src/tests/stub_CommIO.cc
--- squid-3.1.21/src/tests/stub_CommIO.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/tests/stub_CommIO.cc	2012-12-02 23:02:17.000000000 +1300
@@ -1,7 +1,7 @@
 #include "squid.h"
 #include "CommIO.h"
 
-bool CommIO::Initialised = false;
+bool CommIO::Initialized = false;
 bool CommIO::DoneSignalled = false;
 int CommIO::DoneFD = -1;
 int CommIO::DoneReadFD = -1;
@@ -13,7 +13,7 @@
 }
 
 void
-CommIO::Initialise()
+CommIO::Initialize()
 {
     fatal("Not Implemented");
 }
diff -u -r -N squid-3.1.21/src/tunnel.cc squid-3.1.22/src/tunnel.cc
--- squid-3.1.21/src/tunnel.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/src/tunnel.cc	2012-12-02 23:02:17.000000000 +1300
@@ -308,9 +308,14 @@
      */
     cbdataInternalLock(this);	/* ??? should be locked by the caller... */
 
-    /* Bump the server connection timeout on any activity */
-    if (!fd_closed(server.fd()))
-        commSetTimeout(server.fd(), Config.Timeout.read, tunnelTimeout, this);
+    /* Bump the source connection timeout on any activity */
+    if (!fd_closed(from.fd()))
+        commSetTimeout(from.fd(), Config.Timeout.read, tunnelTimeout, this);
+
+    /* Bump the dest connection read timeout on any activity */
+    /* see Bug 3659: tunnels can be weird, with very long one-way transfers */
+    if (!fd_closed(to.fd()))
+        commSetTimeout(to.fd(), Config.Timeout.read, tunnelTimeout, this);
 
     if (errcode)
         from.error (xerrno);
diff -u -r -N squid-3.1.21/tools/cachemgr.cc squid-3.1.22/tools/cachemgr.cc
--- squid-3.1.21/tools/cachemgr.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/tools/cachemgr.cc	2012-12-02 23:02:17.000000000 +1300
@@ -586,12 +586,15 @@
     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;
 }
 
@@ -820,7 +823,7 @@
     }
 
     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;
     }
@@ -832,7 +835,7 @@
     } 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;
     }
@@ -846,17 +849,19 @@
 #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;
     }
 
@@ -917,8 +922,6 @@
 read_post_request(void)
 {
     char *s;
-    char *buf;
-    int len;
 
     if ((s = getenv("REQUEST_METHOD")) == NULL)
         return NULL;
@@ -929,15 +932,34 @@
     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.
+    size_t bufLen = (len >= 4096 ? len : 4095);
+    char *buf = (char *)xmalloc(bufLen + 1);
+
+    size_t readLen = fread(buf, bufLen, 1, stdin);
+    if (readLen == 0) {
+        xfree(buf);
+        return NULL;
+    }
+    buf[readLen] = '\0';
+    len -= readLen;
+
+    // purge the remainder of the request entity
+    while (len > 0) {
+        char temp[65535];
+        readLen = fread(temp, 65535, 1, stdin);
+        len -= readLen;
+    }
 
     return buf;
 }
@@ -1077,37 +1099,49 @@
     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);
 
@@ -1145,6 +1179,7 @@
 
     snprintf(&buf[stringLength], sizeof(buf) - stringLength, "Proxy-Authorization: Basic %s\r\n", str64);
 
+    xxfree(str64);
     return buf;
 }
 
diff -u -r -N squid-3.1.21/tools/squidclient.cc squid-3.1.22/tools/squidclient.cc
--- squid-3.1.21/tools/squidclient.cc	2012-09-24 02:01:02.000000000 +1200
+++ squid-3.1.22/tools/squidclient.cc	2012-12-02 23:02:17.000000000 +1300
@@ -34,6 +34,7 @@
 
 #include "config.h"
 #include "ip/IpAddress.h"
+#include "ip/tools.h"
 #include "util.h"
 #include "squid_types.h"
 
@@ -206,6 +207,7 @@
     pcount = 0;
     ping_int = 1 * 1000;
 
+    Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing.
     if (argc < 2) {
         usage(argv[0]);		/* need URL */
     } else if (argc >= 2) {
