diff -u -r -N squid-3.5.16/ChangeLog squid-3.5.17/ChangeLog
--- squid-3.5.16/ChangeLog	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/ChangeLog	2016-04-21 00:24:03.000000000 +1200
@@ -1,3 +1,20 @@
+Changes to squid-3.5.17 (20 Apr 2016):
+
+	- Regression Bug 4480: logformat [.width_max]
+	- Regression Bug 4481: varyEvaluateMatch: Oops. Not a Vary match on second attempt
+	- Bug 4495: Unknown SSL option SSL_OP_NO_TICKET
+	- Bug 4493: theObject->sharedMemorySize() == theSegment.size() exception
+	- Bug 4483: ./configure garbles -Og option in CFLAGS
+	- Bug 4482: Solaris GCC 5.2 warning in src/ip/Intercept.cc
+	- Bug 4468: NotNode (!acl) naming: Terminate the name before strncat(name).
+	- Bug 4465: Header forgery detection leads to crash
+	- Bug 2460 partial: workaround deferred reads on shutdown and restart
+	- cachemgr.cgi: use dynamic MemBuf for internal content generation
+	- ESI: Fix several element construction issues
+	- TLS: Fix Handshake Error: ccs received early
+	- TLS: Add chained and signing cert to peek-then-bumped connections
+	- Fix some startup/shutdown crashes
+
 Changes to squid-3.5.16 (02 Apr 2016):
 
 	- Bug 4476: Removed duplicated #include lines
diff -u -r -N squid-3.5.16/configure squid-3.5.17/configure
--- squid-3.5.16/configure	2016-04-02 10:06:42.000000000 +1300
+++ squid-3.5.17/configure	2016-04-21 00:26:08.000000000 +1200
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.16.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.17.
 #
 # Report bugs to <http://bugs.squid-cache.org/>.
 #
@@ -595,8 +595,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='3.5.16'
-PACKAGE_STRING='Squid Web Proxy 3.5.16'
+PACKAGE_VERSION='3.5.17'
+PACKAGE_STRING='Squid Web Proxy 3.5.17'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -1636,7 +1636,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.5.16 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 3.5.17 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1707,7 +1707,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.16:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.17:";;
    esac
   cat <<\_ACEOF
 
@@ -2119,7 +2119,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 3.5.16
+Squid Web Proxy configure 3.5.17
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3223,7 +3223,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.5.16, which was
+It was created by Squid Web Proxy $as_me 3.5.17, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4090,7 +4090,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='3.5.16'
+ VERSION='3.5.17'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20789,8 +20789,8 @@
 if test "x$enableval" = "xno" ; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: Disabling compiler optimizations (-O flag)" >&5
 $as_echo "$as_me: Disabling compiler optimizations (-O flag)" >&6;}
-  CFLAGS="`echo $CFLAGS | sed -e 's/-O[0-9]*//'`"
-  CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-O[0-9]*//'`"
+  CFLAGS="`echo $CFLAGS | sed -e 's/-O[0-9g]*//'`"
+  CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-O[0-9g]*//'`"
   enable_inline="no"
 fi
 
@@ -38623,7 +38623,7 @@
     if test "x$GCC" = "xyes"; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: Removing -O for gcc on $host" >&5
 $as_echo "$as_me: Removing -O for gcc on $host" >&6;}
-      CFLAGS="`echo $CFLAGS | sed -e 's/-O[0-9]*//'`"
+      CFLAGS="`echo $CFLAGS | sed -e 's/-O[0-9g]*//'`"
     fi
   ;;
 
@@ -41872,7 +41872,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.5.16, which was
+This file was extended by Squid Web Proxy $as_me 3.5.17, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -41938,7 +41938,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.5.16
+Squid Web Proxy config.status 3.5.17
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-3.5.16/configure.ac squid-3.5.17/configure.ac
--- squid-3.5.16/configure.ac	2016-04-02 10:06:41.000000000 +1300
+++ squid-3.5.17/configure.ac	2016-04-21 00:26:07.000000000 +1200
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[3.5.16],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[3.5.17],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -399,8 +399,8 @@
                   --disable-inline]), [
 if test "x$enableval" = "xno" ; then
   AC_MSG_NOTICE([Disabling compiler optimizations (-O flag)])
-  CFLAGS="`echo $CFLAGS | sed -e 's/-O[[0-9]]*//'`"
-  CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-O[[0-9]]*//'`"
+  CFLAGS="`echo $CFLAGS | sed -e 's/-O[[0-9g]]*//'`"
+  CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-O[[0-9g]]*//'`"
   enable_inline="no"
 fi
 ])
@@ -3237,7 +3237,7 @@
   i386-*-solaris2.*)
     if test "x$GCC" = "xyes"; then
       AC_MSG_NOTICE([Removing -O for gcc on $host])
-      CFLAGS="`echo $CFLAGS | sed -e 's/-O[[0-9]]*//'`"
+      CFLAGS="`echo $CFLAGS | sed -e 's/-O[[0-9g]]*//'`"
     fi
   ;;
 
diff -u -r -N squid-3.5.16/doc/release-notes/release-3.5.html squid-3.5.17/doc/release-notes/release-3.5.html
--- squid-3.5.16/doc/release-notes/release-3.5.html	2016-04-02 11:42:35.000000000 +1300
+++ squid-3.5.17/doc/release-notes/release-3.5.html	2016-04-21 01:16:07.000000000 +1200
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 3.5.16 release notes</TITLE>
+ <TITLE>Squid 3.5.17 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.16 release notes</H1>
+<H1>Squid 3.5.17 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -64,7 +64,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.5.16.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.17.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.5/">http://www.squid-cache.org/Versions/v3/3.5/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
diff -u -r -N squid-3.5.16/helpers/basic_auth/DB/basic_db_auth.8 squid-3.5.17/helpers/basic_auth/DB/basic_db_auth.8
--- squid-3.5.16/helpers/basic_auth/DB/basic_db_auth.8	2016-04-02 11:42:44.000000000 +1300
+++ squid-3.5.17/helpers/basic_auth/DB/basic_db_auth.8	2016-04-21 01:16:10.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8 squid-3.5.17/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8
--- squid-3.5.16/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-04-02 11:42:55.000000000 +1300
+++ squid-3.5.17/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-04-21 01:16:14.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_MSNT_MULTI_DOMAIN_AUTH 1"
-.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/basic_auth/POP3/basic_pop3_auth.8 squid-3.5.17/helpers/basic_auth/POP3/basic_pop3_auth.8
--- squid-3.5.16/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-04-02 11:43:05.000000000 +1300
+++ squid-3.5.17/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-04-21 01:16:19.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/external_acl/delayer/ext_delayer_acl.8 squid-3.5.17/helpers/external_acl/delayer/ext_delayer_acl.8
--- squid-3.5.16/helpers/external_acl/delayer/ext_delayer_acl.8	2016-04-02 11:43:27.000000000 +1300
+++ squid-3.5.17/helpers/external_acl/delayer/ext_delayer_acl.8	2016-04-21 01:16:33.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/external_acl/SQL_session/ext_sql_session_acl.8 squid-3.5.17/helpers/external_acl/SQL_session/ext_sql_session_acl.8
--- squid-3.5.16/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-04-02 11:43:41.000000000 +1300
+++ squid-3.5.17/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-04-21 01:16:41.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-3.5.17/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-3.5.16/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-04-02 11:43:47.000000000 +1300
+++ squid-3.5.17/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-04-21 01:16:44.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/log_daemon/DB/log_db_daemon.8 squid-3.5.17/helpers/log_daemon/DB/log_db_daemon.8
--- squid-3.5.16/helpers/log_daemon/DB/log_db_daemon.8	2016-04-02 11:43:51.000000000 +1300
+++ squid-3.5.17/helpers/log_daemon/DB/log_db_daemon.8	2016-04-21 01:16:46.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/helpers/storeid_rewrite/file/storeid_file_rewrite.8 squid-3.5.17/helpers/storeid_rewrite/file/storeid_file_rewrite.8
--- squid-3.5.16/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-04-02 11:44:15.000000000 +1300
+++ squid-3.5.17/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-04-21 01:17:00.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2016-04-01" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2016-04-20" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.16/include/version.h squid-3.5.17/include/version.h
--- squid-3.5.16/include/version.h	2016-04-02 10:06:42.000000000 +1300
+++ squid-3.5.17/include/version.h	2016-04-21 00:26:08.000000000 +1200
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1459544569
+#define SQUID_RELEASE_TIME 1461155035
 #endif
 
 /*
diff -u -r -N squid-3.5.16/RELEASENOTES.html squid-3.5.17/RELEASENOTES.html
--- squid-3.5.16/RELEASENOTES.html	2016-04-02 11:42:35.000000000 +1300
+++ squid-3.5.17/RELEASENOTES.html	2016-04-21 01:16:07.000000000 +1200
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 3.5.16 release notes</TITLE>
+ <TITLE>Squid 3.5.17 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.16 release notes</H1>
+<H1>Squid 3.5.17 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -64,7 +64,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.5.16.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.17.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.5/">http://www.squid-cache.org/Versions/v3/3.5/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
diff -u -r -N squid-3.5.16/src/acl/BoolOps.cc squid-3.5.17/src/acl/BoolOps.cc
--- squid-3.5.16/src/acl/BoolOps.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/acl/BoolOps.cc	2016-04-21 00:24:03.000000000 +1200
@@ -17,6 +17,7 @@
 {
     assert(acl);
     name[0] = '!';
+    name[1] = '\0';
     strncat(&name[1], acl->name, sizeof(name)-1-1);
     add(acl);
 }
diff -u -r -N squid-3.5.16/src/cf.data.pre squid-3.5.17/src/cf.data.pre
--- squid-3.5.16/src/cf.data.pre	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/cf.data.pre	2016-04-21 00:24:03.000000000 +1200
@@ -2537,13 +2537,16 @@
 	    NO_TLSv1    Disallow the use of TLSv1.0
 	    NO_TLSv1_1  Disallow the use of TLSv1.1
 	    NO_TLSv1_2  Disallow the use of TLSv1.2
+
 	    SINGLE_DH_USE
 		      Always create a new key when using temporary/ephemeral
 		      DH key exchanges
-	    SSL_OP_NO_TICKET
+
+	    NO_TICKET
 		      Disable use of RFC5077 session tickets. Some servers
 		      may have problems understanding the TLS extension due
 		      to ambiguous specification in RFC4507.
+
 	    ALL       Enable various bug workarounds suggested as "harmless"
 		      by OpenSSL. Be warned that this may reduce SSL/TLS
 		      strength to some attacks.
@@ -3273,9 +3276,16 @@
 			    NO_TLSv1    Disallow the use of TLSv1.0
 			    NO_TLSv1_1  Disallow the use of TLSv1.1
 			    NO_TLSv1_2  Disallow the use of TLSv1.2
+
 			    SINGLE_DH_USE
 				      Always create a new key when using
 				      temporary/ephemeral DH key exchanges
+
+			    NO_TICKET
+				      Disable use of RFC5077 session tickets. Some servers
+				      may have problems understanding the TLS extension due
+				      to ambiguous specification in RFC4507.
+
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
diff -u -r -N squid-3.5.16/src/client_side.cc squid-3.5.17/src/client_side.cc
--- squid-3.5.16/src/client_side.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/client_side.cc	2016-04-21 00:24:03.000000000 +1200
@@ -3997,6 +3997,9 @@
                     bool ret = Ssl::configureSSLUsingPkeyAndCertFromMemory(ssl, reply_message.getBody().c_str(), *port);
                     if (!ret)
                         debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode");
+
+                    SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl);
+                    Ssl::configureUnconfiguredSslContext(sslContext, signAlgorithm, *port);
                 } else {
                     SSL_CTX *ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port);
                     getSslContextDone(ctx, true);
@@ -4155,6 +4158,9 @@
             SSL *ssl = fd_table[clientConnection->fd].ssl;
             if (!Ssl::configureSSL(ssl, certProperties, *port))
                 debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode");
+
+            SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl);
+            Ssl::configureUnconfiguredSslContext(sslContext, certProperties.signAlgorithm, *port);
         } else {
             SSL_CTX *dynCtx = Ssl::generateSslContext(certProperties, *port);
             getSslContextDone(dynCtx, true);
@@ -4170,17 +4176,10 @@
     // Try to add generated ssl context to storage.
     if (port->generateHostCertificates && isNew) {
 
-        if (signAlgorithm == Ssl::algSignTrusted) {
-            // Add signing certificate to the certificates chain
-            X509 *cert = port->signingCert.get();
-            if (SSL_CTX_add_extra_chain_cert(sslContext, cert)) {
-                // increase the certificate lock
-                CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509);
-            } else {
-                const int ssl_error = ERR_get_error();
-                debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL));
-            }
-            Ssl::addChainToSslContext(sslContext, port->certsToChain.get());
+        if (sslContext && (signAlgorithm == Ssl::algSignTrusted)) {
+            Ssl::chainCertificatesToSSLContext(sslContext, *port);
+        } else if (signAlgorithm == Ssl::algSignTrusted) {
+            debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain because SSL context chain is invalid!");
         }
         //else it is self-signed or untrusted do not attrach any certificate
 
diff -u -r -N squid-3.5.16/src/client_side_request.cc squid-3.5.17/src/client_side_request.cc
--- squid-3.5.16/src/client_side_request.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/client_side_request.cc	2016-04-21 00:24:03.000000000 +1200
@@ -554,7 +554,8 @@
 
     debugs(85, DBG_IMPORTANT, "SECURITY ALERT: Host header forgery detected on " <<
            http->getConn()->clientConnection << " (" << A << " does not match " << B << ")");
-    debugs(85, DBG_IMPORTANT, "SECURITY ALERT: By user agent: " << http->request->header.getStr(HDR_USER_AGENT));
+    if (const char *ua = http->request->header.getStr(HDR_USER_AGENT))
+        debugs(85, DBG_IMPORTANT, "SECURITY ALERT: By user agent: " << ua);
     debugs(85, DBG_IMPORTANT, "SECURITY ALERT: on URL: " << urlCanonical(http->request));
 
     // IP address validation for Host: failed. reject the connection.
diff -u -r -N squid-3.5.16/src/comm.cc squid-3.5.17/src/comm.cc
--- squid-3.5.16/src/comm.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/comm.cc	2016-04-21 00:24:03.000000000 +1200
@@ -1743,7 +1743,7 @@
     //       amount of time. We must re-validate that it is active and usable.
 
     // If the connection has been closed already. Cancel this read.
-    if (!Comm::IsConnOpen(read.theRead.conn)) {
+    if (!fd_table || !Comm::IsConnOpen(read.theRead.conn)) {
         if (read.closer != NULL) {
             read.closer->cancel("Connection closed before.");
             read.closer = NULL;
diff -u -r -N squid-3.5.16/src/esi/Esi.cc squid-3.5.17/src/esi/Esi.cc
--- squid-3.5.16/src/esi/Esi.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/esi/Esi.cc	2016-04-21 00:24:03.000000000 +1200
@@ -966,7 +966,7 @@
     ESIElement::Pointer element;
     int specifiedattcount = attrCount * 2;
     char *position;
-    assert (ellen < sizeof (localbuf)); /* prevent unexpected overruns. */
+    Must(ellen < sizeof(localbuf)); /* prevent unexpected overruns. */
 
     debugs(86, 5, "ESIContext::Start: element '" << el << "' with " << specifiedattcount << " tags");
 
@@ -980,15 +980,17 @@
         /* Spit out elements we aren't interested in */
         localbuf[0] = '<';
         localbuf[1] = '\0';
-        assert (xstrncpy (&localbuf[1], el, sizeof(localbuf) - 2));
+        xstrncpy(&localbuf[1], el, sizeof(localbuf) - 2);
         position = localbuf + strlen (localbuf);
 
         for (i = 0; i < specifiedattcount && attr[i]; i += 2) {
+            Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 1);
             *position = ' ';
             ++position;
             /* TODO: handle thisNode gracefully */
-            assert (xstrncpy (position, attr[i], sizeof(localbuf) + (position - localbuf)));
+            xstrncpy(position, attr[i], sizeof(localbuf) - (position - localbuf));
             position += strlen (position);
+            Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 2);
             *position = '=';
             ++position;
             *position = '\"';
@@ -997,18 +999,21 @@
             char ch;
             while ((ch = *chPtr++) != '\0') {
                 if (ch == '\"') {
-                    assert( xstrncpy(position, "&quot;", sizeof(localbuf) + (position-localbuf)) );
+                    Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 6);
+                    xstrncpy(position, "&quot;", sizeof(localbuf) - (position-localbuf));
                     position += 6;
                 } else {
+                    Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 1);
                     *position = ch;
                     ++position;
                 }
             }
-            position += strlen (position);
+            Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 1);
             *position = '\"';
             ++position;
         }
 
+        Must(static_cast<size_t>(position - localbuf) < sizeof(localbuf) - 2);
         *position = '>';
         ++position;
         *position = '\0';
@@ -1094,11 +1099,11 @@
     switch (ESIElement::IdentifyElement (el)) {
 
     case ESIElement::ESI_ELEMENT_NONE:
-        assert (ellen < sizeof (localbuf)); /* prevent unexpected overruns. */
+        Must(ellen < sizeof(localbuf) - 3); /* prevent unexpected overruns. */
         /* Add elements we aren't interested in */
         localbuf[0] = '<';
         localbuf[1] = '/';
-        assert (xstrncpy (&localbuf[2], el, sizeof(localbuf) - 3));
+        xstrncpy(&localbuf[2], el, sizeof(localbuf) - 3);
         position = localbuf + strlen (localbuf);
         *position = '>';
         ++position;
diff -u -r -N squid-3.5.16/src/format/Format.cc squid-3.5.17/src/format/Format.cc
--- squid-3.5.16/src/format/Format.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/format/Format.cc	2016-04-21 00:24:03.000000000 +1200
@@ -323,6 +323,7 @@
         int dofree = 0;
         int64_t outoff = 0;
         int dooff = 0;
+        int doSec = 0;
 
         switch (fmt->type) {
 
@@ -508,6 +509,7 @@
             int precision = fmt->widthMax >=0 ? fmt->widthMax :3;
             snprintf(tmp, sizeof(tmp), "%0*" PRId64 ".%0*d", fmt->zero && (fmt->widthMin - precision - 1 >= 0) ? fmt->widthMin - precision - 1 : 0, static_cast<int64_t>(al->cache.start_time.tv_sec), precision, (int)(al->cache.start_time.tv_usec / fmt->divisor));
             out = tmp;
+            doSec = 1;
         }
         break;
 
@@ -1294,7 +1296,7 @@
             }
 
             // enforce width limits if configured
-            const bool haveMaxWidth = fmt->widthMax >=0 && !doint && !dooff && !fmt->divisor;
+            const bool haveMaxWidth = fmt->widthMax >=0 && !doint && !dooff && !doSec;
             if (haveMaxWidth || fmt->widthMin) {
                 const int minWidth = fmt->widthMin >= 0 ?
                                      fmt->widthMin :0;
diff -u -r -N squid-3.5.16/src/ip/Intercept.cc squid-3.5.17/src/ip/Intercept.cc
--- squid-3.5.16/src/ip/Intercept.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/ip/Intercept.cc	2016-04-21 00:24:03.000000000 +1200
@@ -205,7 +205,7 @@
         // warn once every 10 at critical level, then push down a level each repeated event
         static int warningLevel = DBG_CRITICAL;
         debugs(89, warningLevel, "IPF (IPFilter v4) NAT does not support IPv6. Please upgrade to IPFilter v5.1");
-        warningLevel = ++warningLevel % 10;
+        warningLevel = (warningLevel + 1) % 10;
         return false;
 #else
         natLookup.nl_v = 6;
diff -u -r -N squid-3.5.16/src/ipc/mem/Pointer.h squid-3.5.17/src/ipc/mem/Pointer.h
--- squid-3.5.16/src/ipc/mem/Pointer.h	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/ipc/mem/Pointer.h	2016-04-21 00:24:03.000000000 +1200
@@ -165,7 +165,7 @@
     theSegment.open();
     Must(theSegment.mem());
     theObject = reinterpret_cast<Class*>(theSegment.mem());
-    Must(static_cast<off_t>(theObject->sharedMemorySize()) == theSegment.size());
+    Must(static_cast<off_t>(theObject->sharedMemorySize()) <= theSegment.size());
 }
 
 template <class Class>
diff -u -r -N squid-3.5.16/src/SBufDetailedStats.cc squid-3.5.17/src/SBufDetailedStats.cc
--- squid-3.5.16/src/SBufDetailedStats.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/SBufDetailedStats.cc	2016-04-21 00:24:03.000000000 +1200
@@ -15,42 +15,36 @@
  * external dependencies to the SBuf code
  */
 
-static StatHist sbufDestructTimeStats;
-static StatHist memblobDestructTimeStats;
-
-namespace SBufDetailedStatsHistInitializer
-{
-// run the post-instantiation initialization methods for StatHist objects
-struct Initializer {
-    Initializer() {
-        sbufDestructTimeStats.logInit(100,30.0,128000.0);
-        memblobDestructTimeStats.logInit(100,30.0,128000.0);
-    }
-};
-Initializer initializer;
+static StatHist *
+newStatHist() {
+    StatHist *stats = new StatHist;
+    stats->logInit(100, 30.0, 128000.0);
+    return stats;
 }
 
-void
-recordSBufSizeAtDestruct(SBuf::size_type sz)
+StatHist &
+collectSBufDestructTimeStats()
 {
-    sbufDestructTimeStats.count(static_cast<double>(sz));
+    static StatHist *stats = newStatHist();
+    return *stats;
 }
 
-const StatHist *
-collectSBufDestructTimeStats()
+StatHist &
+collectMemBlobDestructTimeStats()
 {
-    return &sbufDestructTimeStats;
+    static StatHist *stats = newStatHist();
+    return *stats;
 }
 
 void
-recordMemBlobSizeAtDestruct(SBuf::size_type sz)
+recordSBufSizeAtDestruct(SBuf::size_type sz)
 {
-    memblobDestructTimeStats.count(static_cast<double>(sz));
+    collectSBufDestructTimeStats().count(static_cast<double>(sz));
 }
 
-const StatHist *
-collectMemBlobDestructTimeStats()
+void
+recordMemBlobSizeAtDestruct(SBuf::size_type sz)
 {
-    return &memblobDestructTimeStats;
+    collectMemBlobDestructTimeStats().count(static_cast<double>(sz));
 }
 
diff -u -r -N squid-3.5.16/src/SBufDetailedStats.h squid-3.5.17/src/SBufDetailedStats.h
--- squid-3.5.16/src/SBufDetailedStats.h	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/SBufDetailedStats.h	2016-04-21 00:24:03.000000000 +1200
@@ -16,20 +16,14 @@
 /// Record the size a SBuf had when it was destructed
 void recordSBufSizeAtDestruct(SBuf::size_type sz);
 
-/** Collect the SBuf size-at-destruct-time histogram
- *
- * \note the returned StatHist object must not be freed
- */
-const StatHist * collectSBufDestructTimeStats();
+/// the SBuf size-at-destruct-time histogram
+StatHist &collectSBufDestructTimeStats();
 
 /// Record the size a MemBlob had when it was destructed
 void recordMemBlobSizeAtDestruct(MemBlob::size_type sz);
 
-/** Collect the MemBlob size-at-destruct-time histogram
- *
- * \note the returned StatHist object must not be freed
- */
-const StatHist * collectMemBlobDestructTimeStats();
+/// the MemBlob size-at-destruct-time histogram
+StatHist &collectMemBlobDestructTimeStats();
 
 #endif /* SQUID_SBUFDETAILEDSTATS_H */
 
diff -u -r -N squid-3.5.16/src/SBufStatsAction.cc squid-3.5.17/src/SBufStatsAction.cc
--- squid-3.5.16/src/SBufStatsAction.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/SBufStatsAction.cc	2016-04-21 00:24:03.000000000 +1200
@@ -38,8 +38,8 @@
 {
     sbdata = SBuf::GetStats();
     mbdata = MemBlob::GetStats();
-    sbsizesatdestruct = *collectSBufDestructTimeStats();
-    mbsizesatdestruct = *collectMemBlobDestructTimeStats();
+    sbsizesatdestruct = collectSBufDestructTimeStats();
+    mbsizesatdestruct = collectMemBlobDestructTimeStats();
 }
 
 static void
diff -u -r -N squid-3.5.16/src/ssl/bio.cc squid-3.5.17/src/ssl/bio.cc
--- squid-3.5.16/src/ssl/bio.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/ssl/bio.cc	2016-04-21 00:24:03.000000000 +1200
@@ -515,9 +515,7 @@
         return clientFeatures.sessionId == serverFeatures.sessionId;
 
     // is this a session resuming attempt using TLS tickets?
-    if (clientFeatures.hasTlsTicket &&
-            serverFeatures.tlsTicketsExtension &&
-            serverFeatures.hasCcsOrNst)
+    if (clientFeatures.hasTlsTicket && serverFeatures.hasCcsOrNst)
         return true;
 
     return false;
diff -u -r -N squid-3.5.16/src/ssl/support.cc squid-3.5.17/src/ssl/support.cc
--- squid-3.5.16/src/ssl/support.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/ssl/support.cc	2016-04-21 00:24:03.000000000 +1200
@@ -1697,6 +1697,30 @@
     return createSSLContext(cert, pkey, port);
 }
 
+void
+Ssl::chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
+{
+    assert(sslContext != NULL);
+    // Add signing certificate to the certificates chain
+    X509 *signingCert = port.signingCert.get();
+    if (SSL_CTX_add_extra_chain_cert(sslContext, signingCert)) {
+        // increase the certificate lock
+        CRYPTO_add(&(signingCert->references),1,CRYPTO_LOCK_X509);
+    } else {
+        const int ssl_error = ERR_get_error();
+        debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL));
+    }
+    Ssl::addChainToSslContext(sslContext, port.certsToChain.get());
+}
+
+void
+Ssl::configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port)
+{
+    if (sslContext && signAlgorithm == Ssl::algSignTrusted) {
+        Ssl::chainCertificatesToSSLContext(sslContext, port);
+    }
+}
+
 bool
 Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
 {
diff -u -r -N squid-3.5.16/src/ssl/support.h squid-3.5.17/src/ssl/support.h
--- squid-3.5.16/src/ssl/support.h	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/ssl/support.h	2016-04-21 00:24:03.000000000 +1200
@@ -247,6 +247,18 @@
 SSL_CTX * createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port);
 
 /**
+ \ingroup ServerProtocolSSLAPI
+ * Chain signing certificate and chained certificates to an SSL Context
+ */
+void chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port);
+
+/**
+ \ingroup ServerProtocolSSLAPI
+ * Configure a previously unconfigured SSL context object.
+ */
+void configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port);
+
+/**
   \ingroup ServerProtocolSSLAPI
   * Generates a certificate and a private key using provided properies and set it
   * to SSL object.
diff -u -r -N squid-3.5.16/src/StoreMetaVary.cc squid-3.5.17/src/StoreMetaVary.cc
--- squid-3.5.16/src/StoreMetaVary.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/StoreMetaVary.cc	2016-04-21 00:24:03.000000000 +1200
@@ -22,6 +22,9 @@
         /* XXX separate this mutator from the query */
         /* Assume the object is OK.. remember the vary request headers */
         e->mem_obj->vary_headers.assign(static_cast<const char *>(value), length);
+        /* entries created before SBuf vary handling may include string terminator */
+        static const SBuf nul("\0", 1);
+        e->mem_obj->vary_headers.trim(nul);
         return true;
     }
 
diff -u -r -N squid-3.5.16/src/store_swapmeta.cc squid-3.5.17/src/store_swapmeta.cc
--- squid-3.5.16/src/store_swapmeta.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/store_swapmeta.cc	2016-04-21 00:24:03.000000000 +1200
@@ -89,9 +89,7 @@
     SBuf vary(e->mem_obj->vary_headers);
 
     if (!vary.isEmpty()) {
-        // TODO: do we still need +1 here? StoreMetaVary::checkConsistency
-        //       no longer relies on nul-termination, but other things might.
-        t = StoreMeta::Factory(STORE_META_VARY_HEADERS, vary.length() + 1, vary.c_str());
+        t = StoreMeta::Factory(STORE_META_VARY_HEADERS, vary.length(), vary.c_str());
 
         if (!t) {
             storeSwapTLVFree(TLV);
diff -u -r -N squid-3.5.16/src/tests/stub_cbdata.cc squid-3.5.17/src/tests/stub_cbdata.cc
--- squid-3.5.16/src/tests/stub_cbdata.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/tests/stub_cbdata.cc	2016-04-21 00:24:03.000000000 +1200
@@ -13,7 +13,13 @@
 #include "tests/STUB.h"
 
 void cbdataRegisterWithCacheManager(void) STUB
-
+void *cbdataInternalAlloc(cbdata_type type, const char *, int sz) {
+    return xcalloc(1, sz);
+}
+void *cbdataInternalFree(void *p, const char *, int) {
+    xfree(p);
+    return NULL;
+}
 #if USE_CBDATA_DEBUG
 void *cbdataInternalAllocDbg(cbdata_type type, const char *, int) STUB_RETVAL(NULL)
 void *cbdataInternalFreeDbg(void *p, const char *, int) STUB_RETVAL(NULL)
diff -u -r -N squid-3.5.16/src/tests/stub_mem.cc squid-3.5.17/src/tests/stub_mem.cc
--- squid-3.5.16/src/tests/stub_mem.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/src/tests/stub_mem.cc	2016-04-21 00:24:03.000000000 +1200
@@ -14,7 +14,7 @@
 
 #define STUB_API "stub_mem.cc"
 #include "Mem.h"
-#include "STUB.h"
+#include "tests/STUB.h"
 
 void
 memFreeString(size_t size, void *buf)
diff -u -r -N squid-3.5.16/test-suite/stub_cbdata.cc squid-3.5.17/test-suite/stub_cbdata.cc
--- squid-3.5.16/test-suite/stub_cbdata.cc	2016-04-02 11:46:28.000000000 +1300
+++ squid-3.5.17/test-suite/stub_cbdata.cc	2016-04-21 01:18:11.000000000 +1200
@@ -13,7 +13,13 @@
 #include "tests/STUB.h"
 
 void cbdataRegisterWithCacheManager(void) STUB
-
+void *cbdataInternalAlloc(cbdata_type type, const char *, int sz) {
+    return xcalloc(1, sz);
+}
+void *cbdataInternalFree(void *p, const char *, int) {
+    xfree(p);
+    return NULL;
+}
 #if USE_CBDATA_DEBUG
 void *cbdataInternalAllocDbg(cbdata_type type, const char *, int) STUB_RETVAL(NULL)
 void *cbdataInternalFreeDbg(void *p, const char *, int) STUB_RETVAL(NULL)
diff -u -r -N squid-3.5.16/tools/cachemgr.cc squid-3.5.17/tools/cachemgr.cc
--- squid-3.5.16/tools/cachemgr.cc	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/tools/cachemgr.cc	2016-04-21 00:24:03.000000000 +1200
@@ -11,6 +11,7 @@
 #include "getfullhostname.h"
 #include "html_quote.h"
 #include "ip/Address.h"
+#include "MemBuf.h"
 #include "rfc1123.h"
 #include "rfc1738.h"
 #include "util.h"
@@ -423,8 +424,8 @@
     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;
@@ -432,15 +433,14 @@
     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');
 
@@ -452,59 +452,56 @@
 
     /* 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);
+        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);
+            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);
+                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
                 /* highlight protected but probably available entries */
                 if (!strcmp(p, "protected"))
-                    snprintf(html, sizeof(html), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n",
-                             a_url, d);
+                    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;
     }
 
@@ -514,7 +511,7 @@
     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);
@@ -531,18 +528,17 @@
             ++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);
+        out.Printf("<%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");
+    out.append("</tr>\n", 6);
     next_is_header = is_header && strstr(buf, "\t\t");
     ++table_line_num;
-    return html;
 }
 
 static const char *
@@ -699,14 +695,18 @@
         /* 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 */
diff -u -r -N squid-3.5.16/tools/Makefile.am squid-3.5.17/tools/Makefile.am
--- squid-3.5.16/tools/Makefile.am	2016-04-02 10:02:59.000000000 +1300
+++ squid-3.5.17/tools/Makefile.am	2016-04-21 00:24:03.000000000 +1200
@@ -34,15 +34,24 @@
 stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc
 	cp $(top_srcdir)/src/tests/stub_debug.cc .
 
+MemBuf.cc: $(top_srcdir)/src/MemBuf.cc
+	cp $(top_srcdir)/src/MemBuf.cc $@
+
 time.cc: $(top_srcdir)/src/time.cc
 	cp $(top_srcdir)/src/time.cc .
 
+stub_cbdata.cc: $(top_srcdir)/src/tests/stub_cbdata.cc
+	cp $(top_srcdir)/src/tests/stub_cbdata.cc $@
+
+stub_mem.cc: $(top_srcdir)/src/tests/stub_mem.cc
+	cp $(top_srcdir)/src/tests/stub_mem.cc $@
+
 # stock tools for unit tests - library independent versions of dlink_list
 # etc.
 # globals.cc is needed by test_tools.cc.
 # Neither of these should be disted from here.
 TESTSOURCES= test_tools.cc
-CLEANFILES += test_tools.cc stub_debug.cc time.cc
+CLEANFILES += test_tools.cc MemBuf.cc stub_debug.cc time.cc stub_cbdata.cc stub_mem.cc
 
 ## ##### helper-mux #####
 
@@ -60,7 +69,10 @@
 libexec_PROGRAMS = cachemgr$(CGIEXT)
 
 cachemgr__CGIEXT__SOURCES = cachemgr.cc \
+	MemBuf.cc \
+	stub_cbdata.cc \
 	stub_debug.cc \
+	stub_mem.cc \
 	test_tools.cc \
 	time.cc
 
diff -u -r -N squid-3.5.16/tools/Makefile.in squid-3.5.17/tools/Makefile.in
--- squid-3.5.16/tools/Makefile.in	2016-04-02 10:06:17.000000000 +1300
+++ squid-3.5.17/tools/Makefile.in	2016-04-21 00:25:57.000000000 +1200
@@ -164,7 +164,10 @@
 	"$(DESTDIR)$(man8dir)"
 PROGRAMS = $(libexec_PROGRAMS)
 am_cachemgr__CGIEXT__OBJECTS = cachemgr__CGIEXT_-cachemgr.$(OBJEXT) \
+	cachemgr__CGIEXT_-MemBuf.$(OBJEXT) \
+	cachemgr__CGIEXT_-stub_cbdata.$(OBJEXT) \
 	cachemgr__CGIEXT_-stub_debug.$(OBJEXT) \
+	cachemgr__CGIEXT_-stub_mem.$(OBJEXT) \
 	cachemgr__CGIEXT_-test_tools.$(OBJEXT) \
 	cachemgr__CGIEXT_-time.$(OBJEXT)
 cachemgr__CGIEXT__OBJECTS = $(am_cachemgr__CGIEXT__OBJECTS)
@@ -728,7 +731,8 @@
 top_srcdir = @top_srcdir@
 AM_CFLAGS = $(SQUID_CFLAGS)
 AM_CXXFLAGS = $(SQUID_CXXFLAGS)
-CLEANFILES = test_tools.cc stub_debug.cc time.cc cachemgr.cgi.8
+CLEANFILES = test_tools.cc MemBuf.cc stub_debug.cc time.cc \
+	stub_cbdata.cc stub_mem.cc cachemgr.cgi.8
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
 	-I$(top_srcdir)/lib -I$(top_srcdir)/src \
 	-I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(KRB5INCS) \
@@ -767,7 +771,10 @@
 libexec_SCRIPTS = helper-mux.pl
 DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf
 cachemgr__CGIEXT__SOURCES = cachemgr.cc \
+	MemBuf.cc \
+	stub_cbdata.cc \
 	stub_debug.cc \
+	stub_mem.cc \
 	test_tools.cc \
 	time.cc
 
@@ -910,8 +917,11 @@
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-cachemgr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-stub_debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-test_tools.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachemgr__CGIEXT_-time.Po@am__quote@
 
@@ -953,6 +963,34 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-cachemgr.obj `if test -f 'cachemgr.cc'; then $(CYGPATH_W) 'cachemgr.cc'; else $(CYGPATH_W) '$(srcdir)/cachemgr.cc'; fi`
 
+cachemgr__CGIEXT_-MemBuf.o: MemBuf.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-MemBuf.o -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Tpo -c -o cachemgr__CGIEXT_-MemBuf.o `test -f 'MemBuf.cc' || echo '$(srcdir)/'`MemBuf.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Tpo $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='MemBuf.cc' object='cachemgr__CGIEXT_-MemBuf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-MemBuf.o `test -f 'MemBuf.cc' || echo '$(srcdir)/'`MemBuf.cc
+
+cachemgr__CGIEXT_-MemBuf.obj: MemBuf.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-MemBuf.obj -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Tpo -c -o cachemgr__CGIEXT_-MemBuf.obj `if test -f 'MemBuf.cc'; then $(CYGPATH_W) 'MemBuf.cc'; else $(CYGPATH_W) '$(srcdir)/MemBuf.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Tpo $(DEPDIR)/cachemgr__CGIEXT_-MemBuf.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='MemBuf.cc' object='cachemgr__CGIEXT_-MemBuf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-MemBuf.obj `if test -f 'MemBuf.cc'; then $(CYGPATH_W) 'MemBuf.cc'; else $(CYGPATH_W) '$(srcdir)/MemBuf.cc'; fi`
+
+cachemgr__CGIEXT_-stub_cbdata.o: stub_cbdata.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-stub_cbdata.o -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Tpo -c -o cachemgr__CGIEXT_-stub_cbdata.o `test -f 'stub_cbdata.cc' || echo '$(srcdir)/'`stub_cbdata.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Tpo $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='stub_cbdata.cc' object='cachemgr__CGIEXT_-stub_cbdata.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-stub_cbdata.o `test -f 'stub_cbdata.cc' || echo '$(srcdir)/'`stub_cbdata.cc
+
+cachemgr__CGIEXT_-stub_cbdata.obj: stub_cbdata.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-stub_cbdata.obj -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Tpo -c -o cachemgr__CGIEXT_-stub_cbdata.obj `if test -f 'stub_cbdata.cc'; then $(CYGPATH_W) 'stub_cbdata.cc'; else $(CYGPATH_W) '$(srcdir)/stub_cbdata.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Tpo $(DEPDIR)/cachemgr__CGIEXT_-stub_cbdata.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='stub_cbdata.cc' object='cachemgr__CGIEXT_-stub_cbdata.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-stub_cbdata.obj `if test -f 'stub_cbdata.cc'; then $(CYGPATH_W) 'stub_cbdata.cc'; else $(CYGPATH_W) '$(srcdir)/stub_cbdata.cc'; fi`
+
 cachemgr__CGIEXT_-stub_debug.o: stub_debug.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-stub_debug.o -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-stub_debug.Tpo -c -o cachemgr__CGIEXT_-stub_debug.o `test -f 'stub_debug.cc' || echo '$(srcdir)/'`stub_debug.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-stub_debug.Tpo $(DEPDIR)/cachemgr__CGIEXT_-stub_debug.Po
@@ -967,6 +1005,20 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-stub_debug.obj `if test -f 'stub_debug.cc'; then $(CYGPATH_W) 'stub_debug.cc'; else $(CYGPATH_W) '$(srcdir)/stub_debug.cc'; fi`
 
+cachemgr__CGIEXT_-stub_mem.o: stub_mem.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-stub_mem.o -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Tpo -c -o cachemgr__CGIEXT_-stub_mem.o `test -f 'stub_mem.cc' || echo '$(srcdir)/'`stub_mem.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Tpo $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='stub_mem.cc' object='cachemgr__CGIEXT_-stub_mem.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-stub_mem.o `test -f 'stub_mem.cc' || echo '$(srcdir)/'`stub_mem.cc
+
+cachemgr__CGIEXT_-stub_mem.obj: stub_mem.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-stub_mem.obj -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Tpo -c -o cachemgr__CGIEXT_-stub_mem.obj `if test -f 'stub_mem.cc'; then $(CYGPATH_W) 'stub_mem.cc'; else $(CYGPATH_W) '$(srcdir)/stub_mem.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Tpo $(DEPDIR)/cachemgr__CGIEXT_-stub_mem.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='stub_mem.cc' object='cachemgr__CGIEXT_-stub_mem.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -c -o cachemgr__CGIEXT_-stub_mem.obj `if test -f 'stub_mem.cc'; then $(CYGPATH_W) 'stub_mem.cc'; else $(CYGPATH_W) '$(srcdir)/stub_mem.cc'; fi`
+
 cachemgr__CGIEXT_-test_tools.o: test_tools.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cachemgr__CGIEXT__CXXFLAGS) $(CXXFLAGS) -MT cachemgr__CGIEXT_-test_tools.o -MD -MP -MF $(DEPDIR)/cachemgr__CGIEXT_-test_tools.Tpo -c -o cachemgr__CGIEXT_-test_tools.o `test -f 'test_tools.cc' || echo '$(srcdir)/'`test_tools.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cachemgr__CGIEXT_-test_tools.Tpo $(DEPDIR)/cachemgr__CGIEXT_-test_tools.Po
@@ -1505,9 +1557,18 @@
 stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc
 	cp $(top_srcdir)/src/tests/stub_debug.cc .
 
+MemBuf.cc: $(top_srcdir)/src/MemBuf.cc
+	cp $(top_srcdir)/src/MemBuf.cc $@
+
 time.cc: $(top_srcdir)/src/time.cc
 	cp $(top_srcdir)/src/time.cc .
 
+stub_cbdata.cc: $(top_srcdir)/src/tests/stub_cbdata.cc
+	cp $(top_srcdir)/src/tests/stub_cbdata.cc $@
+
+stub_mem.cc: $(top_srcdir)/src/tests/stub_mem.cc
+	cp $(top_srcdir)/src/tests/stub_mem.cc $@
+
 cachemgr.cgi.8: $(srcdir)/cachemgr.cgi.8.in Makefile
 	$(SUBSTITUTE) < $(srcdir)/cachemgr.cgi.8.in > $@
 
diff -u -r -N squid-3.5.16/tools/MemBuf.cc squid-3.5.17/tools/MemBuf.cc
--- squid-3.5.16/tools/MemBuf.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-3.5.17/tools/MemBuf.cc	2016-04-21 01:18:13.000000000 +1200
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 59    auto-growing Memory Buffer with printf */
+
+/**
+ \verbatim
+ * Rationale:
+ * ----------
+ *
+ * Here is how one would Comm::Write an object without MemBuffer:
+ *
+ * {
+ * -- allocate:
+ * buf = malloc(big_enough);
+ *
+ * -- "pack":
+ * snprintf object(s) piece-by-piece constantly checking for overflows
+ * and maintaining (buf+offset);
+ * ...
+ *
+ * -- write
+ * Comm::Write(buf, free, ...);
+ * }
+ *
+ * The whole "packing" idea is quite messy: We are given a buffer of fixed
+ * size and we have to check all the time that we still fit. Sounds logical.
+ *
+ * However, what happens if we have more data? If we are lucky to stop before
+ * we overrun any buffers, we still may have garbage (e.g. half of ETag) in
+ * the buffer.
+ *
+ * MemBuffer:
+ * ----------
+ *
+ * MemBuffer is a memory-resident buffer with printf()-like interface. It
+ * hides all offest handling and overflow checking. Moreover, it has a
+ * build-in control that no partial data has been written.
+ *
+ * MemBuffer is designed to handle relatively small data. It starts with a
+ * small buffer of configurable size to avoid allocating huge buffers all the
+ * time.  MemBuffer doubles the buffer when needed. It assert()s that it will
+ * not grow larger than a configurable limit. MemBuffer has virtually no
+ * overhead (and can even reduce memory consumption) compared to old
+ * "packing" approach.
+ *
+ * MemBuffer eliminates both "packing" mess and truncated data:
+ *
+ * {
+ * -- setup
+ * MemBuf buf;
+ *
+ * -- required init with optional size tuning (see #defines for defaults)
+ * buf.init(initial-size, absolute-maximum);
+ *
+ * -- "pack" (no need to handle offsets or check for overflows)
+ * buf.Printf(...);
+ * ...
+ *
+ * -- write
+ * Comm::Write(fd, buf, callback);
+ *
+ * -- *iff* you did not give the buffer away, free it yourself
+ * -- buf.clean();
+ * }
+ \endverbatim
+ */
+
+#include "squid.h"
+#include "Mem.h"
+#include "MemBuf.h"
+#include "profiler/Profiler.h"
+
+#ifdef VA_COPY
+#undef VA_COPY
+#endif
+#if defined HAVE_VA_COPY
+#define VA_COPY va_copy
+#elif defined HAVE___VA_COPY
+#define VA_COPY __va_copy
+#endif
+
+/* local constants */
+
+/* default values for buffer sizes, used by memBufDefInit */
+#define MEM_BUF_INIT_SIZE   (2*1024)
+#define MEM_BUF_MAX_SIZE    (2*1000*1024*1024)
+
+CBDATA_CLASS_INIT(MemBuf);
+
+/** init with defaults */
+void
+MemBuf::init()
+{
+    init(MEM_BUF_INIT_SIZE, MEM_BUF_MAX_SIZE);
+}
+
+/** init with specific sizes */
+void
+MemBuf::init(mb_size_t szInit, mb_size_t szMax)
+{
+    assert(szInit > 0 && szMax > 0);
+    buf = NULL;
+    size = 0;
+    max_capacity = szMax;
+    capacity = 0;
+    stolen = 0;
+    grow(szInit);
+    terminate();
+}
+
+/**
+ * cleans the mb; last function to call if you do not give .buf away with
+ * memBufFreeFunc
+ */
+void
+MemBuf::clean()
+{
+    if (isNull()) {
+        // nothing to do
+    } else {
+        assert(buf);
+        assert(!stolen);    /* not frozen */
+
+        memFreeBuf(capacity, buf);
+        buf = NULL;
+        size = capacity = max_capacity = 0;
+    }
+}
+
+/**
+ * Cleans the buffer without changing its capacity
+ * if called with a Null buffer, calls memBufDefInit()
+ */
+void
+MemBuf::reset()
+{
+    if (isNull()) {
+        init();
+    } else {
+        assert(!stolen);    /* not frozen */
+        /* reset */
+        memset(buf, 0, capacity);
+        size = 0;
+    }
+}
+
+/**
+ * Unfortunate hack to test if the buffer has been Init()ialized
+ */
+int
+MemBuf::isNull()
+{
+    if (!buf && !max_capacity && !capacity && !size)
+        return 1;       /* is null (not initialized) */
+
+    assert(buf && max_capacity && capacity);    /* paranoid */
+
+    return 0;
+}
+
+mb_size_t MemBuf::spaceSize() const
+{
+    const mb_size_t terminatedSize = size + 1;
+    return (terminatedSize < capacity) ? capacity - terminatedSize : 0;
+}
+
+mb_size_t MemBuf::potentialSpaceSize() const
+{
+    const mb_size_t terminatedSize = size + 1;
+    return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0;
+}
+
+/// removes sz bytes and "packs" by moving content left
+void MemBuf::consume(mb_size_t shiftSize)
+{
+    const mb_size_t cSize = contentSize();
+    assert(0 <= shiftSize && shiftSize <= cSize);
+    assert(!stolen); /* not frozen */
+
+    PROF_start(MemBuf_consume);
+    if (shiftSize > 0) {
+        if (shiftSize < cSize)
+            memmove(buf, buf + shiftSize, cSize - shiftSize);
+
+        size -= shiftSize;
+
+        terminate();
+    }
+    PROF_stop(MemBuf_consume);
+}
+
+/// removes all whitespace prefix bytes and "packs" by moving content left
+void MemBuf::consumeWhitespacePrefix()
+{
+    PROF_start(MemBuf_consumeWhitespace);
+    if (contentSize() > 0) {
+        const char *end = buf + contentSize();
+        const char *p = buf;
+        for (; p<end && xisspace(*p); ++p);
+        if (p-buf > 0)
+            consume(p-buf);
+    }
+    PROF_stop(MemBuf_consumeWhitespace);
+}
+
+// removes last tailSize bytes
+void MemBuf::truncate(mb_size_t tailSize)
+{
+    const mb_size_t cSize = contentSize();
+    assert(0 <= tailSize && tailSize <= cSize);
+    assert(!stolen); /* not frozen */
+    size -= tailSize;
+}
+
+/**
+ * calls memcpy, appends exactly size bytes,
+ * extends buffer or creates buffer if needed.
+ */
+void MemBuf::append(const char *newContent, mb_size_t sz)
+{
+    assert(sz >= 0);
+    assert(buf || (0==capacity && 0==size));
+    assert(!stolen); /* not frozen */
+
+    PROF_start(MemBuf_append);
+    if (sz > 0) {
+        if (size + sz + 1 > capacity)
+            grow(size + sz + 1);
+
+        assert(size + sz <= capacity); /* paranoid */
+        memcpy(space(), newContent, sz);
+        appended(sz);
+    }
+    PROF_stop(MemBuf_append);
+}
+
+/// updates content size after external append
+void MemBuf::appended(mb_size_t sz)
+{
+    assert(size + sz <= capacity);
+    size += sz;
+    terminate();
+}
+
+/**
+ * Null-terminate in case we are used as a string.
+ * Extra octet is not counted in the content size (or space size)
+ *
+ \note XXX: but the extra octet is counted when growth decisions are made!
+ *     This will cause the buffer to grow when spaceSize() == 1 on append,
+ *     which will assert() if the buffer cannot grow any more.
+ */
+void MemBuf::terminate()
+{
+    assert(size < capacity);
+    *space() = '\0';
+}
+
+/* calls memBufVPrintf */
+void
+MemBuf::Printf(const char *fmt,...)
+{
+    va_list args;
+    va_start(args, fmt);
+    vPrintf(fmt, args);
+    va_end(args);
+}
+
+/**
+ * vPrintf for other printf()'s to use; calls vsnprintf, extends buf if needed
+ */
+void
+MemBuf::vPrintf(const char *fmt, va_list vargs)
+{
+#ifdef VA_COPY
+    va_list ap;
+#endif
+
+    int sz = 0;
+    assert(fmt);
+    assert(buf);
+    assert(!stolen);    /* not frozen */
+    /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
+
+    while (capacity <= max_capacity) {
+        mb_size_t free_space = capacity - size;
+        /* put as much as we can */
+
+#ifdef VA_COPY
+        /* Fix of bug 753r. The value of vargs is undefined
+         * after vsnprintf() returns. Make a copy of vargs
+         * incase we loop around and call vsnprintf() again.
+         */
+        VA_COPY(ap,vargs);
+        sz = vsnprintf(buf + size, free_space, fmt, ap);
+        va_end(ap);
+#else /* VA_COPY */
+
+        sz = vsnprintf(buf + size, free_space, fmt, vargs);
+#endif /*VA_COPY*/
+        /* check for possible overflow */
+        /* snprintf on Linuz returns -1 on overflows */
+        /* snprintf on FreeBSD returns at least free_space on overflows */
+
+        if (sz < 0 || sz >= free_space)
+            grow(capacity + 1);
+        else
+            break;
+    }
+
+    size += sz;
+    /* on Linux and FreeBSD, '\0' is not counted in return value */
+    /* on XXX it might be counted */
+    /* check that '\0' is appended and not counted */
+
+    if (!size || buf[size - 1]) {
+        assert(!buf[size]);
+    } else {
+        --size;
+    }
+}
+
+/**
+ * Important:
+ *   calling this function "freezes" mb,
+ *   do not _update_ mb after that in any way
+ *   (you still can read-access .buf and .size)
+ *
+ \retval free() function to be used.
+ */
+FREE *
+MemBuf::freeFunc()
+{
+    FREE *ff;
+    assert(buf);
+    assert(!stolen);    /* not frozen */
+
+    ff = memFreeBufFunc((size_t) capacity);
+    stolen = 1;     /* freeze */
+    return ff;
+}
+
+/**
+ * Grows (doubles) internal buffer to satisfy required minimal capacity
+ */
+void
+MemBuf::grow(mb_size_t min_cap)
+{
+    size_t new_cap;
+    size_t buf_cap;
+
+    assert(!stolen);
+    assert(capacity < min_cap);
+
+    PROF_start(MemBuf_grow);
+
+    /* determine next capacity */
+
+    if (min_cap > 64 * 1024) {
+        new_cap = 64 * 1024;
+
+        while (new_cap < (size_t) min_cap)
+            new_cap += 64 * 1024;   /* increase in reasonable steps */
+    } else {
+        new_cap = (size_t) min_cap;
+    }
+
+    /* last chance to fit before we assert(!overflow) */
+    if (new_cap > (size_t) max_capacity)
+        new_cap = (size_t) max_capacity;
+
+    assert(new_cap <= (size_t) max_capacity);   /* no overflow */
+
+    assert(new_cap > (size_t) capacity);    /* progress */
+
+    buf_cap = (size_t) capacity;
+
+    buf = (char *)memReallocBuf(buf, new_cap, &buf_cap);
+
+    /* done */
+    capacity = (mb_size_t) buf_cap;
+    PROF_stop(MemBuf_grow);
+}
+
+/* Reports */
+
+/**
+ * Puts report on MemBuf _module_ usage into mb
+ */
+void
+memBufReport(MemBuf * mb)
+{
+    assert(mb);
+    mb->Printf("memBufReport is not yet implemented @?@\n");
+}
+
+#if !_USE_INLINE_
+#include "MemBuf.cci"
+#endif
+
diff -u -r -N squid-3.5.16/tools/stub_cbdata.cc squid-3.5.17/tools/stub_cbdata.cc
--- squid-3.5.16/tools/stub_cbdata.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-3.5.17/tools/stub_cbdata.cc	2016-04-21 01:18:13.000000000 +1200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "cbdata.h"
+
+#define STUB_API "cbdata.cc"
+#include "tests/STUB.h"
+
+void cbdataRegisterWithCacheManager(void) STUB
+void *cbdataInternalAlloc(cbdata_type type, const char *, int sz) {
+    return xcalloc(1, sz);
+}
+void *cbdataInternalFree(void *p, const char *, int) {
+    xfree(p);
+    return NULL;
+}
+#if USE_CBDATA_DEBUG
+void *cbdataInternalAllocDbg(cbdata_type type, const char *, int) STUB_RETVAL(NULL)
+void *cbdataInternalFreeDbg(void *p, const char *, int) STUB_RETVAL(NULL)
+void cbdataInternalLockDbg(const void *p, const char *, int) STUB
+void cbdataInternalUnlockDbg(const void *p, const char *, int) STUB
+int cbdataInternalReferenceDoneValidDbg(void **p, void **tp, const char *, int) STUB_RETVAL(0)
+#else
+void *cbdataInternalAlloc(cbdata_type type) STUB_RETVAL(NULL)
+void *cbdataInternalFree(void *p) STUB_RETVAL(NULL)
+void cbdataInternalLock(const void *p) STUB
+void cbdataInternalUnlock(const void *p) STUB
+int cbdataInternalReferenceDoneValid(void **p, void **tp) STUB_RETVAL(0)
+#endif
+
+int cbdataReferenceValid(const void *p) STUB_RETVAL(0)
+cbdata_type cbdataInternalAddType(cbdata_type type, const char *label, int size, FREE * free_func) STUB_RETVAL(CBDATA_UNKNOWN)
+
diff -u -r -N squid-3.5.16/tools/stub_mem.cc squid-3.5.17/tools/stub_mem.cc
--- squid-3.5.16/tools/stub_mem.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-3.5.17/tools/stub_mem.cc	2016-04-21 01:18:14.000000000 +1200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * stub file for mem.cc
+ */
+
+#include "squid.h"
+
+#define STUB_API "stub_mem.cc"
+#include "Mem.h"
+#include "tests/STUB.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)
+{
+    // let's waste plenty of memory. This should cover any possible need
+    return xmalloc(64*1024);
+}
+void memFree(void *p, int type)
+{
+    xfree(p);
+}
+void Mem::Init(void) STUB_NOP
+void memDataInit(mem_type, const char *, size_t, int, bool) STUB_NOP
+int memInUse(mem_type) STUB_RETVAL(0)
+void memConfigure(void) STUB_NOP
+
