diff -u -r -N squid-3.5.15/ChangeLog squid-3.5.16/ChangeLog
--- squid-3.5.15/ChangeLog	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/ChangeLog	2016-04-02 10:02:59.000000000 +1300
@@ -1,3 +1,21 @@
+Changes to squid-3.5.16 (02 Apr 2016):
+
+	- Bug 4476: Removed duplicated #include lines
+	- Bug 4452: squid -z segfaults with ufs
+	- Bug 4447:FwdState.cc:447 "serverConnection() == conn" assertion
+	- Bug 4423: adding stdio: prefix to cache_log directive produces FATAL error
+	- Bug 4409: compile error when two Heimdal libraries are installed
+	- Bug 2831: Cache-control: max-age not sent on TCP_IMS_HIT/304
+	- pinger: Fix buffer overflow in Icmp6::Recv
+	- pinger: Fix select(2) to actually use max_fd
+	- pinger: drop capabilities on Linux
+	- Fix memory leak of HttpRequest objects
+	- Fix memory leak when the cache of sslcrtvalidator_program is disabled via ttl=0
+	- Fix assertion failed: Write.cc:41: "!ccb->active()"
+	- Fix crash on shutdown while cleaning up idle ICAP connections
+	- RFC 7725: Add registry entry for 451 status text
+	- ... and some build issues
+
 Changes to squid-3.5.15 (23 Feb 2016):
 
 	- Bug 3870: assertion failed: String.cc: 'len_ + len <65536' in ESI::CustomParser
diff -u -r -N squid-3.5.15/configure squid-3.5.16/configure
--- squid-3.5.15/configure	2016-02-24 05:28:54.000000000 +1300
+++ squid-3.5.16/configure	2016-04-02 10:06:42.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.69 for Squid Web Proxy 3.5.15.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.16.
 #
 # 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.15'
-PACKAGE_STRING='Squid Web Proxy 3.5.15'
+PACKAGE_VERSION='3.5.16'
+PACKAGE_STRING='Squid Web Proxy 3.5.16'
 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.15 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 3.5.16 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.15:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.16:";;
    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.15
+Squid Web Proxy configure 3.5.16
 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.15, which was
+It was created by Squid Web Proxy $as_me 3.5.16, 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.15'
+ VERSION='3.5.16'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20688,7 +20688,7 @@
     SQUID_CFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wcomments -Wshadow"
     ;;
   esac
-  SQUID_CXXFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wcomments -Wshadow"
+  SQUID_CXXFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wcomments -Wshadow -Woverloaded-virtual"
 else
   SQUID_CFLAGS=
   SQUID_CXXFLAGS=
@@ -21804,15 +21804,18 @@
       fi
       ;;
     rock)
-	if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \
-	  "x$squid_disk_module_candidates_Blocking" != "xyes"; then
-	  as_fn_error $? "Storage module Rock requires IpcIo or Blocking DiskIO module" "$LINENO" 5
-	fi
-	squid_do_build_rock=true
-	;;
+      if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \
+        "x$squid_disk_module_candidates_Blocking" != "xyes"; then
+         as_fn_error $? "Storage module Rock requires DiskIO module: Blocking or IpcIo" "$LINENO" 5
+      fi
+      squid_do_build_rock=true
+      ;;
     ufs)
-	squid_do_build_ufs=true
-	;;
+      if test "x$squid_disk_module_candidates_Blocking" != "xyes"; then
+        as_fn_error $? "Storage module ufs requires DiskIO module: Blocking" "$LINENO" 5
+      fi
+      squid_do_build_ufs=true
+      ;;
     esac
 done
 
@@ -27731,7 +27734,7 @@
   squid_pc_krb5_name="heimdal-gssapi"
 fi
   fi
-  if test "x$squid_pc_krb5_name" != "x" -a "$cross_compiling" = "no"; then
+  if test "x$squid_pc_krb5_name" = "x" -a "$cross_compiling" = "no"; then
     # Look for krb5-config (unless cross-compiling)
     # Extract the first word of "krb5-config", so it can be a program name with args.
 set dummy krb5-config; ac_word=$2
@@ -27777,7 +27780,7 @@
     if test "x$ac_cv_path_krb5_config" != "xno" ; then
       krb5confpath="`dirname $ac_cv_path_krb5_config`"
       ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
-      if test "x$with_heimdal_krb5" = "xyes"; then
+      if test "x$with_heimdal_krb5" = "xyes" -a $ac_heimdal = 0; then
         as_fn_error $? "Could not find pkg-config or krb5-config for Heimdal Kerberos" "$LINENO" 5
       fi
     else
@@ -41869,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.15, which was
+This file was extended by Squid Web Proxy $as_me 3.5.16, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -41935,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.15
+Squid Web Proxy config.status 3.5.16
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-3.5.15/configure.ac squid-3.5.16/configure.ac
--- squid-3.5.15/configure.ac	2016-02-24 05:28:54.000000000 +1300
+++ squid-3.5.16/configure.ac	2016-04-02 10:06:41.000000000 +1300
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[3.5.15],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[3.5.16],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -371,7 +371,7 @@
     SQUID_CFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wcomments -Wshadow"
     ;;
   esac
-  SQUID_CXXFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wcomments -Wshadow"
+  SQUID_CXXFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wcomments -Wshadow -Woverloaded-virtual"
 else
   SQUID_CFLAGS=
   SQUID_CXXFLAGS=
@@ -833,15 +833,18 @@
       fi
       ;;
     rock)
-	if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \
-	  "x$squid_disk_module_candidates_Blocking" != "xyes"; then
-	  AC_MSG_ERROR([Storage module Rock requires IpcIo or Blocking DiskIO module])
-	fi
-	squid_do_build_rock=true
-	;;
+      if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \
+        "x$squid_disk_module_candidates_Blocking" != "xyes"; then
+         AC_MSG_ERROR([Storage module Rock requires DiskIO module: Blocking or IpcIo])
+      fi
+      squid_do_build_rock=true
+      ;;
     ufs)
-	squid_do_build_ufs=true
-	;;
+      if test "x$squid_disk_module_candidates_Blocking" != "xyes"; then
+        AC_MSG_ERROR([Storage module ufs requires DiskIO module: Blocking])
+      fi
+      squid_do_build_ufs=true
+      ;;
     esac
 done
  
@@ -1640,13 +1643,13 @@
   if test "x$squid_pc_krb5_name" = "x"; then
     PKG_CHECK_EXISTS(heimdal-gssapi, [squid_pc_krb5_name="heimdal-gssapi"])
   fi
-  if test "x$squid_pc_krb5_name" != "x" -a "$cross_compiling" = "no"; then
+  if test "x$squid_pc_krb5_name" = "x" -a "$cross_compiling" = "no"; then
     # Look for krb5-config (unless cross-compiling)
     AC_PATH_PROG(krb5_config,krb5-config,no)
     if test "x$ac_cv_path_krb5_config" != "xno" ; then
       krb5confpath="`dirname $ac_cv_path_krb5_config`"
       ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
-      if test "x$with_heimdal_krb5" = "xyes"; then
+      if test "x$with_heimdal_krb5" = "xyes" -a $ac_heimdal = 0; then
         AC_MSG_ERROR([Could not find pkg-config or krb5-config for Heimdal Kerberos])
       fi
     else
diff -u -r -N squid-3.5.15/doc/release-notes/release-3.5.html squid-3.5.16/doc/release-notes/release-3.5.html
--- squid-3.5.15/doc/release-notes/release-3.5.html	2016-02-24 06:14:19.000000000 +1300
+++ squid-3.5.16/doc/release-notes/release-3.5.html	2016-04-02 11:42:35.000000000 +1300
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 3.5.15 release notes</TITLE>
+ <TITLE>Squid 3.5.16 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.15 release notes</H1>
+<H1>Squid 3.5.16 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.15.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.16.</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.15/helpers/basic_auth/DB/basic_db_auth.8 squid-3.5.16/helpers/basic_auth/DB/basic_db_auth.8
--- squid-3.5.15/helpers/basic_auth/DB/basic_db_auth.8	2016-02-24 06:14:23.000000000 +1300
+++ squid-3.5.16/helpers/basic_auth/DB/basic_db_auth.8	2016-04-02 11:42:44.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2016-04-01" "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.15/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
--- squid-3.5.15/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-02-24 06:14:29.000000000 +1300
+++ squid-3.5.16/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-04-02 11:42:55.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_MSNT_MULTI_DOMAIN_AUTH 1"
-.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-04-01" "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.15/helpers/basic_auth/POP3/basic_pop3_auth.8 squid-3.5.16/helpers/basic_auth/POP3/basic_pop3_auth.8
--- squid-3.5.15/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-02-24 06:14:33.000000000 +1300
+++ squid-3.5.16/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-04-02 11:43:05.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2016-04-01" "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.15/helpers/external_acl/delayer/ext_delayer_acl.8 squid-3.5.16/helpers/external_acl/delayer/ext_delayer_acl.8
--- squid-3.5.15/helpers/external_acl/delayer/ext_delayer_acl.8	2016-02-24 06:14:47.000000000 +1300
+++ squid-3.5.16/helpers/external_acl/delayer/ext_delayer_acl.8	2016-04-02 11:43:27.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2016-04-01" "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.15/helpers/external_acl/SQL_session/ext_sql_session_acl.8 squid-3.5.16/helpers/external_acl/SQL_session/ext_sql_session_acl.8
--- squid-3.5.15/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-02-24 06:14:54.000000000 +1300
+++ squid-3.5.16/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-04-02 11:43:41.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2016-04-01" "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.15/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-3.5.16/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-3.5.15/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-02-24 06:14:57.000000000 +1300
+++ squid-3.5.16/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-04-02 11:43:47.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2016-04-01" "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.15/helpers/log_daemon/DB/log_db_daemon.8 squid-3.5.16/helpers/log_daemon/DB/log_db_daemon.8
--- squid-3.5.15/helpers/log_daemon/DB/log_db_daemon.8	2016-02-24 06:14:59.000000000 +1300
+++ squid-3.5.16/helpers/log_daemon/DB/log_db_daemon.8	2016-04-02 11:43:51.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2016-04-01" "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.15/helpers/storeid_rewrite/file/storeid_file_rewrite.8 squid-3.5.16/helpers/storeid_rewrite/file/storeid_file_rewrite.8
--- squid-3.5.15/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-02-24 06:15:12.000000000 +1300
+++ squid-3.5.16/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-04-02 11:44:15.000000000 +1300
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2016-02-23" "perl v5.22.1" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2016-04-01" "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.15/include/version.h squid-3.5.16/include/version.h
--- squid-3.5.15/include/version.h	2016-02-24 05:28:55.000000000 +1300
+++ squid-3.5.16/include/version.h	2016-04-02 10:06:42.000000000 +1300
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1456244734
+#define SQUID_RELEASE_TIME 1459544569
 #endif
 
 /*
diff -u -r -N squid-3.5.15/RELEASENOTES.html squid-3.5.16/RELEASENOTES.html
--- squid-3.5.15/RELEASENOTES.html	2016-02-24 06:14:19.000000000 +1300
+++ squid-3.5.16/RELEASENOTES.html	2016-04-02 11:42:35.000000000 +1300
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 3.5.15 release notes</TITLE>
+ <TITLE>Squid 3.5.16 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.15 release notes</H1>
+<H1>Squid 3.5.16 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.15.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.16.</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.15/src/acl/Asn.cc squid-3.5.16/src/acl/Asn.cc
--- squid-3.5.15/src/acl/Asn.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/acl/Asn.cc	2016-04-02 10:02:59.000000000 +1300
@@ -26,7 +26,6 @@
 #include "SquidConfig.h"
 #include "Store.h"
 #include "StoreClient.h"
-#include "StoreClient.h"
 
 #define WHOIS_PORT 43
 #define AS_REQBUF_SZ    4096
diff -u -r -N squid-3.5.15/src/clients/Client.h squid-3.5.16/src/clients/Client.h
--- squid-3.5.15/src/clients/Client.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/clients/Client.h	2016-04-02 10:02:59.000000000 +1300
@@ -104,7 +104,9 @@
     virtual void sentRequestBody(const CommIoCbParams &io) = 0;
     virtual void doneSendingRequestBody() = 0;
 
-    virtual void closeServer() = 0;            /**< end communication with the server */
+    /// Use this to end communication with the server. The call cancels our
+    /// closure handler and tells FwdState to forget about the connection.
+    virtual void closeServer() = 0;
     virtual bool doneWithServer() const = 0;   /**< did we end communication? */
     /// whether we may receive more virgin response body bytes
     virtual bool mayReadVirginReplyBody() const = 0;
diff -u -r -N squid-3.5.15/src/clients/FtpRelay.cc squid-3.5.16/src/clients/FtpRelay.cc
--- squid-3.5.15/src/clients/FtpRelay.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/clients/FtpRelay.cc	2016-04-02 10:02:59.000000000 +1300
@@ -42,7 +42,7 @@
     void serverState(const Ftp::ServerState newState);
 
     /* Ftp::Client API */
-    virtual void failed(err_type error = ERR_NONE, int xerrno = 0);
+    virtual void failed(err_type error = ERR_NONE, int xerrno = 0, ErrorState *ftperr = NULL);
     virtual void dataChannelConnected(const CommConnectCbParams &io);
 
     /* Client API */
@@ -56,6 +56,7 @@
 
     /* AsyncJob API */
     virtual void start();
+    virtual void swanSong();
 
     void forwardReply();
     void forwardError(err_type error = ERR_NONE, int xerrno = 0);
@@ -87,12 +88,18 @@
     void readUserOrPassReply();
 
     void scheduleReadControlReply();
-    void finalizeDataDownload();
+
+    /// Inform Ftp::Server that we are done if originWaitInProgress
+    void stopOriginWait(int code);
 
     static void abort(void *d); // TODO: Capitalize this and FwdState::abort().
 
     bool forwardingCompleted; ///< completeForwarding() has been called
 
+    /// whether we are between Ftp::Server::startWaitingForOrigin() and
+    /// Ftp::Server::stopWaitingForOrigin() calls
+    bool originWaitInProgress;
+
     struct {
         wordlist *message; ///< reply message, one  wordlist entry per message line
         char *lastCommand; ///< the command caused the reply
@@ -142,7 +149,8 @@
     AsyncJob("Ftp::Relay"),
     Ftp::Client(fwdState),
     thePreliminaryCb(NULL),
-    forwardingCompleted(false)
+    forwardingCompleted(false),
+    originWaitInProgress(false)
 {
     savedReply.message = NULL;
     savedReply.lastCommand = NULL;
@@ -178,11 +186,20 @@
         sendCommand();
 }
 
+void
+Ftp::Relay::swanSong()
+{
+    stopOriginWait(0);
+    Ftp::Client::swanSong();
+}
+
 /// Keep control connection for future requests, after we are done with it.
 /// Similar to COMPLETE_PERSISTENT_MSG handling in http.cc.
 void
 Ftp::Relay::serverComplete()
 {
+    stopOriginWait(ctrl.replycode);
+
     CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
     if (mgr.valid()) {
         if (Comm::IsConnOpen(ctrl.conn)) {
@@ -255,7 +272,7 @@
 }
 
 void
-Ftp::Relay::failed(err_type error, int xerrno)
+Ftp::Relay::failed(err_type error, int xerrno, ErrorState *ftpErr)
 {
     if (!doneWithServer())
         serverState(fssError);
@@ -264,7 +281,7 @@
     if (entry->isEmpty())
         failedErrorMessage(error, xerrno); // as a reply
 
-    Ftp::Client::failed(error, xerrno);
+    Ftp::Client::failed(error, xerrno, ftpErr);
 }
 
 void
@@ -527,6 +544,19 @@
         serverState() == fssConnected ? SENT_USER :
         serverState() == fssHandlePass ? SENT_PASS :
         SENT_COMMAND;
+
+    if (state == SENT_DATA_REQUEST) {
+        CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
+        if (mgr.valid()) {
+            if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
+                typedef NullaryMemFunT<Ftp::Server> CbDialer;
+                AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, srv,
+                                                      Ftp::Server::startWaitingForOrigin);
+                ScheduleCallHere(call);
+                originWaitInProgress = true;
+            }
+        }
+    }
 }
 
 void
@@ -683,7 +713,9 @@
                " after reading response data");
     }
 
-    finalizeDataDownload();
+    debugs(9, 2, "Complete data downloading");
+
+    serverComplete();
 }
 
 void
@@ -711,25 +743,6 @@
     Ftp::Client::scheduleReadControlReply(0);
 }
 
-void
-Ftp::Relay::finalizeDataDownload()
-{
-    debugs(9, 2, "Complete data downloading/Uploading");
-
-    updateMaster().waitForOriginData = false;
-
-    CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
-    if (mgr.valid()) {
-        if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
-            typedef NullaryMemFunT<Ftp::Server> CbDialer;
-            AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, srv,
-                                                  Ftp::Server::originDataCompletionCheckpoint);
-            ScheduleCallHere(call);
-        }
-    }
-    serverComplete();
-}
-
 bool
 Ftp::Relay::abortOnData(const char *reason)
 {
@@ -750,6 +763,23 @@
 }
 
 void
+Ftp::Relay::stopOriginWait(int code)
+{
+    if (originWaitInProgress) {
+        CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
+        if (mgr.valid()) {
+            if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
+                typedef UnaryMemFunT<Ftp::Server, int> CbDialer;
+                AsyncCall::Pointer call = asyncCall(11, 3, "Ftp::Server::stopWaitingForOrigin",
+                                                    CbDialer(srv, &Ftp::Server::stopWaitingForOrigin, code));
+                ScheduleCallHere(call);
+            }
+        }
+        originWaitInProgress = false;
+    }
+}
+
+void
 Ftp::Relay::abort(void *d)
 {
     Ftp::Relay *ftpClient = (Ftp::Relay *)d;
diff -u -r -N squid-3.5.15/src/client_side.cc squid-3.5.16/src/client_side.cc
--- squid-3.5.15/src/client_side.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/client_side.cc	2016-04-02 10:02:59.000000000 +1300
@@ -639,6 +639,7 @@
     }
 
     if (request) {
+        HTTPMSGUNLOCK(al->adapted_request);
         al->adapted_request = request;
         HTTPMSGLOCK(al->adapted_request);
     }
@@ -4683,20 +4684,19 @@
 int
 varyEvaluateMatch(StoreEntry * entry, HttpRequest * request)
 {
-    const char *vary = request->vary_headers;
+    SBuf vary(request->vary_headers);
     int has_vary = entry->getReply()->header.has(HDR_VARY);
 #if X_ACCELERATOR_VARY
-
     has_vary |=
         entry->getReply()->header.has(HDR_X_ACCELERATOR_VARY);
 #endif
 
-    if (!has_vary || !entry->mem_obj->vary_headers) {
-        if (vary) {
+    if (!has_vary || entry->mem_obj->vary_headers.isEmpty()) {
+        if (!vary.isEmpty()) {
             /* Oops... something odd is going on here.. */
             debugs(33, DBG_IMPORTANT, "varyEvaluateMatch: Oops. Not a Vary object on second attempt, '" <<
                    entry->mem_obj->urlXXX() << "' '" << vary << "'");
-            safe_free(request->vary_headers);
+            request->vary_headers.clear();
             return VARY_CANCEL;
         }
 
@@ -4710,8 +4710,8 @@
          */
         vary = httpMakeVaryMark(request, entry->getReply());
 
-        if (vary) {
-            request->vary_headers = xstrdup(vary);
+        if (!vary.isEmpty()) {
+            request->vary_headers = vary;
             return VARY_OTHER;
         } else {
             /* Ouch.. we cannot handle this kind of variance */
@@ -4719,18 +4719,18 @@
             return VARY_CANCEL;
         }
     } else {
-        if (!vary) {
+        if (vary.isEmpty()) {
             vary = httpMakeVaryMark(request, entry->getReply());
 
-            if (vary)
-                request->vary_headers = xstrdup(vary);
+            if (!vary.isEmpty())
+                request->vary_headers = vary;
         }
 
-        if (!vary) {
+        if (vary.isEmpty()) {
             /* Ouch.. we cannot handle this kind of variance */
             /* XXX This cannot really happen, but just to be complete */
             return VARY_CANCEL;
-        } else if (strcmp(vary, entry->mem_obj->vary_headers) == 0) {
+        } else if (vary.cmp(entry->mem_obj->vary_headers) == 0) {
             return VARY_MATCH;
         } else {
             /* Oops.. we have already been here and still haven't
diff -u -r -N squid-3.5.15/src/client_side_reply.cc squid-3.5.16/src/client_side_reply.cc
--- squid-3.5.15/src/client_side_reply.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/client_side_reply.cc	2016-04-02 10:02:59.000000000 +1300
@@ -20,7 +20,6 @@
 #include "format/Token.h"
 #include "FwdState.h"
 #include "globals.h"
-#include "globals.h"
 #include "HttpHeaderTools.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
@@ -988,9 +987,8 @@
     }
 
     /* And for Vary, release the base URI if none of the headers was included in the request */
-
-    if (http->request->vary_headers
-            && !strstr(http->request->vary_headers, "=")) {
+    if (!http->request->vary_headers.isEmpty()
+            && http->request->vary_headers.find('=') != SBuf::npos) {
         StoreEntry *entry = storeGetPublic(urlCanonical(http->request), Http::METHOD_GET);
 
         if (entry) {
diff -u -r -N squid-3.5.15/src/comm.cc squid-3.5.16/src/comm.cc
--- squid-3.5.15/src/comm.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/comm.cc	2016-04-02 10:02:59.000000000 +1300
@@ -976,7 +976,7 @@
     return Comm::COMM_ERROR;
 }
 
-void
+AsyncCall::Pointer
 comm_add_close_handler(int fd, CLCB * handler, void *data)
 {
     debugs(5, 5, "comm_add_close_handler: FD " << fd << ", handler=" <<
@@ -985,6 +985,7 @@
     AsyncCall::Pointer call=commCbCall(5,4, "SomeCloseHandler",
                                        CommCloseCbPtrFun(handler, data));
     comm_add_close_handler(fd, call);
+    return call;
 }
 
 void
diff -u -r -N squid-3.5.15/src/comm.h squid-3.5.16/src/comm.h
--- squid-3.5.15/src/comm.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/comm.h	2016-04-02 10:02:59.000000000 +1300
@@ -79,7 +79,7 @@
 void commCloseAllSockets(void);
 void checkTimeouts(void);
 
-void comm_add_close_handler(int fd, CLCB *, void *);
+AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *, void *);
 void comm_add_close_handler(int fd, AsyncCall::Pointer &);
 void comm_remove_close_handler(int fd, CLCB *, void *);
 void comm_remove_close_handler(int fd, AsyncCall::Pointer &);
diff -u -r -N squid-3.5.15/src/debug.cc squid-3.5.16/src/debug.cc
--- squid-3.5.15/src/debug.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/debug.cc	2016-04-02 10:02:59.000000000 +1300
@@ -222,7 +222,14 @@
     if (debug_log && debug_log != stderr)
         fclose(debug_log);
 
-    debug_log = fopen(logfile, "a+");
+    // Bug 4423: ignore the stdio: logging module name if present
+    const char *logfilename;
+    if (strncmp(logfile, "stdio:",6) == 0)
+        logfilename = logfile + 6;
+    else
+        logfilename = logfile;
+
+    debug_log = fopen(logfilename, "a+");
 
     if (!debug_log) {
         fprintf(stderr, "WARNING: Cannot write log file: %s\n", logfile);
diff -u -r -N squid-3.5.15/src/eui/Eui48.cc squid-3.5.16/src/eui/Eui48.cc
--- squid-3.5.15/src/eui/Eui48.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/eui/Eui48.cc	2016-04-02 10:02:59.000000000 +1300
@@ -181,6 +181,7 @@
         close(tmpSocket);
 
         if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
+            debugs(28, 4, "id=" << (void*)this << " ... not an Ethernet interface: " << arpReq.arp_ha.sa_data);
             clear();
             return false;
         }
diff -u -r -N squid-3.5.15/src/FwdState.cc squid-3.5.16/src/FwdState.cc
--- squid-3.5.15/src/FwdState.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/FwdState.cc	2016-04-02 10:02:59.000000000 +1300
@@ -119,7 +119,8 @@
 FwdState::closeServerConnection(const char *reason)
 {
     debugs(17, 3, "because " << reason << "; " << serverConn);
-    comm_remove_close_handler(serverConn->fd, fwdServerClosedWrapper, this);
+    comm_remove_close_handler(serverConn->fd, closeHandler);
+    closeHandler = NULL;
     fwdPconnPool->noteUses(fd_table[serverConn->fd].pconn.uses);
     serverConn->close();
 }
@@ -446,7 +447,8 @@
     debugs(17, 3, HERE << entry->url() );
     assert(serverConnection() == conn);
     assert(Comm::IsConnOpen(conn));
-    comm_remove_close_handler(conn->fd, fwdServerClosedWrapper, this);
+    comm_remove_close_handler(conn->fd, closeHandler);
+    closeHandler = NULL;
     serverConn = NULL;
 }
 
@@ -677,7 +679,7 @@
     serverConn = conn;
     debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
 
-    comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
+    closeHandler = comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
 
 #if USE_OPENSSL
     if (!request->flags.pinned) {
@@ -833,7 +835,8 @@
             request->flags.pinned = true;
             if (pinned_connection->pinnedAuth())
                 request->flags.auth = true;
-            comm_add_close_handler(serverConn->fd, fwdServerClosedWrapper, this);
+
+            closeHandler = comm_add_close_handler(serverConn->fd,  fwdServerClosedWrapper, this);
 
             syncWithServerConn(pinned_connection->pinning.host);
 
@@ -872,7 +875,7 @@
         debugs(17, 3, HERE << "reusing pconn " << serverConnection());
         ++n_tries;
 
-        comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
+        closeHandler = comm_add_close_handler(serverConnection()->fd,  fwdServerClosedWrapper, this);
 
         syncWithServerConn(request->GetHost());
 
diff -u -r -N squid-3.5.15/src/FwdState.h squid-3.5.16/src/FwdState.h
--- squid-3.5.15/src/FwdState.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/FwdState.h	2016-04-02 10:02:59.000000000 +1300
@@ -152,6 +152,8 @@
 
     Comm::ConnectionPointer serverConn; ///< a successfully opened connection to a server.
 
+    AsyncCall::Pointer closeHandler; ///< The serverConn close handler
+
     /// possible pconn race states
     typedef enum { raceImpossible, racePossible, raceHappened } PconnRace;
     PconnRace pconnRace; ///< current pconn race state
diff -u -r -N squid-3.5.15/src/http/StatusCode.cc squid-3.5.16/src/http/StatusCode.cc
--- squid-3.5.15/src/http/StatusCode.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/http/StatusCode.cc	2016-04-02 10:02:59.000000000 +1300
@@ -212,6 +212,10 @@
         return "Request Header Fields Too Large";
         break;
 
+    case scUnavailableForLegalReasons:
+        return "Unavailable For Legal Reasons";
+        break;
+
     // 500-599
     case Http::scInternalServerError:
         return "Internal Server Error";
diff -u -r -N squid-3.5.15/src/http/StatusCode.h squid-3.5.16/src/http/StatusCode.h
--- squid-3.5.15/src/http/StatusCode.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/http/StatusCode.h	2016-04-02 10:02:59.000000000 +1300
@@ -66,6 +66,7 @@
     scPreconditionRequired = 428,   /**< RFC6585 */
     scTooManyRequests = 429,        /**< RFC6585 */
     scRequestHeaderFieldsTooLarge = 431, /**< RFC6585 */
+    scUnavailableForLegalReasons = 451, /**< RFC7725 */
     scInternalServerError = 500,
     scNotImplemented = 501,
     scBadGateway = 502,
diff -u -r -N squid-3.5.15/src/http.cc squid-3.5.16/src/http.cc
--- squid-3.5.15/src/http.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/http.cc	2016-04-02 10:02:59.000000000 +1300
@@ -165,7 +165,8 @@
         fwd->fail(new ErrorState(ERR_READ_TIMEOUT, Http::scGatewayTimeout, fwd->request));
     }
 
-    serverConnection->close();
+    closeServer();
+    mustStop("HttpStateData::httpTimeout");
 }
 
 /// Remove an existing public store entry if the incoming response (to be
@@ -574,9 +575,9 @@
 /*
  * For Vary, store the relevant request headers as
  * virtual headers in the reply
- * Returns false if the variance cannot be stored
+ * Returns an empty SBuf if the variance cannot be stored
  */
-const char *
+SBuf
 httpMakeVaryMark(HttpRequest * request, HttpReply const * reply)
 {
     String vary, hdr;
@@ -584,9 +585,9 @@
     const char *item;
     const char *value;
     int ilen;
-    static String vstr;
+    SBuf vstr;
+    static const SBuf asterisk("*");
 
-    vstr.clean();
     vary = reply->header.getList(HDR_VARY);
 
     while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
@@ -597,11 +598,13 @@
         if (strcmp(name, "*") == 0) {
             /* Can not handle "Vary: *" withtout ETag support */
             safe_free(name);
-            vstr.clean();
+            vstr.clear();
             break;
         }
 
-        strListAdd(&vstr, name, ',');
+        if (!vstr.isEmpty())
+            vstr.append(", ", 2);
+        vstr.append(name);
         hdr = request->header.getByName(name);
         safe_free(name);
         value = hdr.termedBuf();
@@ -626,7 +629,17 @@
         char *name = (char *)xmalloc(ilen + 1);
         xstrncpy(name, item, ilen + 1);
         Tolower(name);
-        strListAdd(&vstr, name, ',');
+
+        if (strcmp(name, "*") == 0) {
+            /* Can not handle "Vary: *" withtout ETag support */
+            safe_free(name);
+            vstr.clear();
+            break;
+        }
+
+        if (!vstr.isEmpty())
+            vstr.append(", ", 2);
+        vstr.append(name);
         hdr = request->header.getByName(name);
         safe_free(name);
         value = hdr.termedBuf();
@@ -644,8 +657,8 @@
     vary.clean();
 #endif
 
-    debugs(11, 3, "httpMakeVaryMark: " << vstr);
-    return vstr.termedBuf();
+    debugs(11, 3, vstr);
+    return vstr;
 }
 
 void
@@ -915,15 +928,15 @@
             || rep->header.has(HDR_X_ACCELERATOR_VARY)
 #endif
        ) {
-        const char *vary = httpMakeVaryMark(request, rep);
+        const SBuf vary(httpMakeVaryMark(request, rep));
 
-        if (!vary) {
+        if (vary.isEmpty()) {
             entry->makePrivate();
             if (!fwd->reforwardableStatus(rep->sline.status()))
                 EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
             varyFailure = true;
         } else {
-            entry->mem_obj->vary_headers = xstrdup(vary);
+            entry->mem_obj->vary_headers = vary;
         }
     }
 
@@ -1150,7 +1163,8 @@
             err->xerrno = io.xerrno;
             fwd->fail(err);
             flags.do_next_read = false;
-            serverConnection->close();
+            closeServer();
+            mustStop("HttpStateData::readReply");
         }
 
         return;
@@ -1306,7 +1320,8 @@
     entry->reset();
     fwd->fail(new ErrorState(error, Http::scBadGateway, fwd->request));
     flags.do_next_read = false;
-    serverConnection->close();
+    closeServer();
+    mustStop("HttpStateData::continueAfterParsingHeader");
     return false; // quit on error
 }
 
@@ -1540,7 +1555,8 @@
         ErrorState *err = new ErrorState(ERR_WRITE_ERROR, Http::scBadGateway, fwd->request);
         err->xerrno = io.xerrno;
         fwd->fail(err);
-        serverConnection->close();
+        closeServer();
+        mustStop("HttpStateData::wroteLast");
         return;
     }
 
@@ -1568,7 +1584,6 @@
     request->hier.peer_http_request_sent = current_time;
 }
 
-// Close the HTTP server connection. Used by serverComplete().
 void
 HttpStateData::closeServer()
 {
@@ -2371,7 +2386,8 @@
             debugs(11, DBG_IMPORTANT, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << request->client_addr << "' -> '" << entry->url() << "'" );
 
             if (virginReply()->sline.status() == Http::scInvalidHeader) {
-                serverConnection->close();
+                closeServer();
+                mustStop("HttpStateData::handleMoreRequestBodyAvailable");
                 return;
             }
         }
diff -u -r -N squid-3.5.15/src/http.h squid-3.5.16/src/http.h
--- squid-3.5.15/src/http.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/http.h	2016-04-02 10:02:59.000000000 +1300
@@ -12,6 +12,7 @@
 #include "clients/Client.h"
 #include "comm.h"
 #include "HttpStateFlags.h"
+#include "SBuf.h"
 
 class ChunkedCodingParser;
 class FwdState;
@@ -117,7 +118,7 @@
 
 int httpCachable(const HttpRequestMethod&);
 void httpStart(FwdState *);
-const char *httpMakeVaryMark(HttpRequest * request, HttpReply const * reply);
+SBuf httpMakeVaryMark(HttpRequest * request, HttpReply const * reply);
 
 #endif /* SQUID_HTTP_H */
 
diff -u -r -N squid-3.5.15/src/HttpMsg.cc squid-3.5.16/src/HttpMsg.cc
--- squid-3.5.15/src/HttpMsg.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/HttpMsg.cc	2016-04-02 10:02:59.000000000 +1300
@@ -10,6 +10,7 @@
 
 #include "squid.h"
 #include "Debug.h"
+#include "HttpHdrCc.h"
 #include "HttpHeaderTools.h"
 #include "HttpMsg.h"
 #include "MemBuf.h"
@@ -27,6 +28,25 @@
     assert(!body_pipe);
 }
 
+void
+HttpMsg::putCc(const HttpHdrCc *otherCc)
+{
+    // get rid of the old CC, if any
+    if (cache_control) {
+        delete cache_control;
+        cache_control = NULL;
+        if (!otherCc)
+            header.delById(HDR_CACHE_CONTROL);
+        // else it will be deleted inside putCc() below
+    }
+
+    // add new CC, if any
+    if (otherCc) {
+        cache_control = new HttpHdrCc(*otherCc);
+        header.putCc(cache_control);
+    }
+}
+
 HttpMsgParseState &operator++ (HttpMsgParseState &aState)
 {
     int tmp = (int)aState;
diff -u -r -N squid-3.5.15/src/HttpMsg.h squid-3.5.16/src/HttpMsg.h
--- squid-3.5.15/src/HttpMsg.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/HttpMsg.h	2016-04-02 10:02:59.000000000 +1300
@@ -64,6 +64,9 @@
 
     BodyPipe::Pointer body_pipe; // optional pipeline to receive message body
 
+    /// copies Cache-Control header to this message
+    void putCc(const HttpHdrCc *otherCc);
+
     // returns true and sets hdr_sz on success
     // returns false and sets *error to zero when needs more data
     // returns false and sets *error to a positive Http::StatusCode on error
diff -u -r -N squid-3.5.15/src/HttpReply.cc squid-3.5.16/src/HttpReply.cc
--- squid-3.5.15/src/HttpReply.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/HttpReply.cc	2016-04-02 10:02:59.000000000 +1300
@@ -150,7 +150,6 @@
     rv->last_modified = last_modified;
     rv->expires = expires;
     rv->content_type = content_type;
-    /* rv->cache_control */
     /* rv->content_range */
     /* rv->keep_alive */
     rv->sline.set(Http::ProtocolVersion(1,1), Http::scNotModified, NULL);
@@ -159,6 +158,8 @@
         if ((e = header.findEntry(ImsEntries[t])))
             rv->header.addEntry(e->clone());
 
+    rv->putCc(cache_control);
+
     /* rv->body */
     return rv;
 }
diff -u -r -N squid-3.5.15/src/HttpRequest.cc squid-3.5.16/src/HttpRequest.cc
--- squid-3.5.15/src/HttpRequest.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/HttpRequest.cc	2016-04-02 10:02:59.000000000 +1300
@@ -92,7 +92,7 @@
     peer_login = NULL;      // not allocated/deallocated by this class
     peer_domain = NULL;     // not allocated/deallocated by this class
     peer_host = NULL;
-    vary_headers = NULL;
+    vary_headers = SBuf();
     myportname = null_string;
     tag = null_string;
 #if USE_AUTH
@@ -124,9 +124,7 @@
     auth_user_request = NULL;
 #endif
     safe_free(canonical);
-
-    safe_free(vary_headers);
-
+    vary_headers.clear();
     url.clear();
     urlpath.clean();
 
@@ -203,7 +201,7 @@
 
     copy->lastmod = lastmod;
     copy->etag = etag;
-    copy->vary_headers = vary_headers ? xstrdup(vary_headers) : NULL;
+    copy->vary_headers = vary_headers;
     // XXX: what to do with copy->peer_domain?
 
     copy->tag = tag;
diff -u -r -N squid-3.5.15/src/HttpRequest.h squid-3.5.16/src/HttpRequest.h
--- squid-3.5.15/src/HttpRequest.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/HttpRequest.h	2016-04-02 10:02:59.000000000 +1300
@@ -179,7 +179,8 @@
 
     time_t lastmod;     /* Used on refreshes */
 
-    const char *vary_headers;   /* Used when varying entities are detected. Changes how the store key is calculated */
+    /// The variant second-stage cache key. Generated from Vary header pattern for this request.
+    SBuf vary_headers;
 
     char *peer_domain;      /* Configured peer forceddomain */
 
diff -u -r -N squid-3.5.15/src/icmp/Icmp6.cc squid-3.5.16/src/icmp/Icmp6.cc
--- squid-3.5.15/src/icmp/Icmp6.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/icmp/Icmp6.cc	2016-04-02 10:02:59.000000000 +1300
@@ -256,7 +256,7 @@
     #define ip6_hops    // HOPS!!!  (can it be true??)
 
         ip = (struct ip6_hdr *) pkt;
-        pkt += sizeof(ip6_hdr);
+        NP: echo size needs to +sizeof(ip6_hdr);
 
     debugs(42, DBG_CRITICAL, HERE << "ip6_nxt=" << ip->ip6_nxt <<
             ", ip6_plen=" << ip->ip6_plen <<
@@ -267,7 +267,6 @@
     */
 
     icmp6header = (struct icmp6_hdr *) pkt;
-    pkt += sizeof(icmp6_hdr);
 
     if (icmp6header->icmp6_type != ICMP6_ECHO_REPLY) {
 
@@ -292,7 +291,7 @@
         return;
     }
 
-    echo = (icmpEchoData *) pkt;
+    echo = (icmpEchoData *) (pkt + sizeof(icmp6_hdr));
 
     preply.opcode = echo->opcode;
 
diff -u -r -N squid-3.5.15/src/icmp/pinger.cc squid-3.5.16/src/icmp/pinger.cc
--- squid-3.5.15/src/icmp/pinger.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/icmp/pinger.cc	2016-04-02 10:02:59.000000000 +1300
@@ -162,18 +162,46 @@
     max_fd = max(max_fd, squid_link);
 
     if (setgid(getgid()) < 0) {
-        debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerror());
+        int xerrno = errno;
+        debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerr(xerrno));
         icmp4.Close();
         icmp6.Close();
         exit (1);
     }
     if (setuid(getuid()) < 0) {
-        debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerror());
+        int xerrno = errno;
+        debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerr(xerrno));
         icmp4.Close();
         icmp6.Close();
         exit (1);
     }
 
+#if USE_LIBCAP
+    // Drop remaining capabilities (if installed as non-setuid setcap cap_net_raw=ep).
+    // If pinger binary was installed setuid root, setuid() above already dropped all
+    // capabilities, and this is no-op.
+    cap_t caps;
+    caps = cap_init();
+    if (!caps) {
+        int xerrno = errno;
+        debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_init() failed: " << xstrerr(xerrno));
+        icmp4.Close();
+        icmp6.Close();
+        exit (1);
+    } else {
+        if (cap_set_proc(caps) != 0) {
+            int xerrno = errno;
+            // cap_set_proc(cap_init()) is expected to never fail
+            debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_set_proc(none) failed: " << xstrerr(xerrno));
+            cap_free(caps);
+            icmp4.Close();
+            icmp6.Close();
+            exit (1);
+        }
+        cap_free(caps);
+    }
+#endif
+
     last_check_time = squid_curtime;
 
     for (;;) {
@@ -188,11 +216,12 @@
         }
 
         FD_SET(squid_link, &R);
-        x = select(10, &R, NULL, NULL, &tv);
+        x = select(max_fd+1, &R, NULL, NULL, &tv);
         getCurrentTime();
 
         if (x < 0) {
-            debugs(42, DBG_CRITICAL, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerror());
+            int xerrno = errno;
+            debugs(42, DBG_CRITICAL, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerr(xerrno));
             control.Close();
             exit(1);
         }
diff -u -r -N squid-3.5.15/src/log/access_log.cc squid-3.5.16/src/log/access_log.cc
--- squid-3.5.15/src/log/access_log.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/log/access_log.cc	2016-04-02 10:02:59.000000000 +1300
@@ -17,8 +17,6 @@
 #include "CachePeer.h"
 #include "err_detail_type.h"
 #include "errorpage.h"
-#include "errorpage.h"
-#include "errorpage.h"
 #include "format/Token.h"
 #include "globals.h"
 #include "hier_code.h"
diff -u -r -N squid-3.5.15/src/main.cc squid-3.5.16/src/main.cc
--- squid-3.5.15/src/main.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/main.cc	2016-04-02 10:02:59.000000000 +1300
@@ -1899,6 +1899,9 @@
 
     WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
 #endif
+#if ICAP_CLIENT
+    Adaptation::Icap::TheConfig.freeService();
+#endif
 
     Store::Root().sync(); /* Flush pending object writes/unlinks */
 
diff -u -r -N squid-3.5.15/src/MemObject.cc squid-3.5.16/src/MemObject.cc
--- squid-3.5.15/src/MemObject.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/MemObject.cc	2016-04-02 10:02:59.000000000 +1300
@@ -136,8 +136,6 @@
     HTTPMSGUNLOCK(request);
 
     ctx_exit(ctx);              /* must exit before we free mem->url */
-
-    safe_free(vary_headers);
 }
 
 void
@@ -221,8 +219,8 @@
 MemObject::stat(MemBuf * mb) const
 {
     mb->Printf("\t" SQUIDSBUFPH " %s\n", SQUIDSBUFPRINT(method.image()), logUri());
-    if (vary_headers)
-        mb->Printf("\tvary_headers: %s\n", vary_headers);
+    if (!vary_headers.isEmpty())
+        mb->Printf("\tvary_headers: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(vary_headers));
     mb->Printf("\tinmem_lo: %" PRId64 "\n", inmem_lo);
     mb->Printf("\tinmem_hi: %" PRId64 "\n", data_hdr.endOffset());
     mb->Printf("\tswapout: %" PRId64 " bytes queued\n",
diff -u -r -N squid-3.5.15/src/MemObject.h squid-3.5.16/src/MemObject.h
--- squid-3.5.15/src/MemObject.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/MemObject.h	2016-04-02 10:02:59.000000000 +1300
@@ -13,6 +13,7 @@
 #include "dlink.h"
 #include "HttpRequestMethod.h"
 #include "RemovalPolicy.h"
+#include "SBuf.h"
 #include "stmem.h"
 #include "StoreIOBuffer.h"
 #include "StoreIOState.h"
@@ -167,7 +168,7 @@
     unsigned int chksum;
 #endif
 
-    const char *vary_headers;
+    SBuf vary_headers;
 
     void delayRead(DeferredRead const &);
     void kickReads();
diff -u -r -N squid-3.5.15/src/MemStore.cc squid-3.5.16/src/MemStore.cc
--- squid-3.5.15/src/MemStore.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/MemStore.cc	2016-04-02 10:02:59.000000000 +1300
@@ -443,7 +443,7 @@
 
     assert(e.mem_obj);
 
-    if (e.mem_obj->vary_headers) {
+    if (!e.mem_obj->vary_headers.isEmpty()) {
         // XXX: We must store/load SerialisedMetaData to cache Vary in RAM
         debugs(20, 5, "Vary not yet supported: " << e.mem_obj->vary_headers);
         return false;
diff -u -r -N squid-3.5.15/src/servers/FtpServer.cc squid-3.5.16/src/servers/FtpServer.cc
--- squid-3.5.15/src/servers/FtpServer.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/servers/FtpServer.cc	2016-04-02 10:02:59.000000000 +1300
@@ -59,7 +59,9 @@
     uploadAvailSize(0),
     listener(),
     connector(),
-    reader()
+    reader(),
+    waitingForOrigin(false),
+    originDataDownloadAbortedOnError(false)
 {
     flags.readMore = false; // we need to announce ourselves first
     *uploadBuf = 0;
@@ -1033,6 +1035,12 @@
 {
     Must(reply);
 
+    if (waitingForOrigin) {
+        Must(delayedReply == NULL);
+        delayedReply = reply;
+        return;
+    }
+
     const HttpHeader &header = reply->header;
     // adaptation and forwarding errors lack HDR_FTP_STATUS
     if (!header.has(HDR_FTP_STATUS)) {
@@ -1489,8 +1497,8 @@
     if (!checkDataConnPre())
         return false;
 
-    master->waitForOriginData = true;
     master->userDataDone = 0;
+    originDataDownloadAbortedOnError = false;
 
     changeState(fssHandleDataRequest, "handleDataRequest");
 
@@ -1503,9 +1511,6 @@
     if (!checkDataConnPre())
         return false;
 
-    master->waitForOriginData = true;
-    master->userDataDone = 0;
-
     changeState(fssHandleUploadRequest, "handleDataRequest");
 
     return true;
@@ -1705,14 +1710,46 @@
 }
 
 void
-Ftp::Server::originDataCompletionCheckpoint()
+Ftp::Server::startWaitingForOrigin()
 {
-    if (!master->userDataDone) {
-        debugs(33, 5, "Transfering from/to client not finished yet");
-        return;
+    debugs(33, 5, "waiting for Ftp::Client data transfer to end");
+    waitingForOrigin = true;
+}
+
+void
+Ftp::Server::stopWaitingForOrigin(int originStatus)
+{
+    Must(waitingForOrigin);
+    waitingForOrigin = false;
+
+    // if we have already decided how to respond, respond now
+    if (delayedReply != NULL) {
+        HttpReply::Pointer reply = delayedReply;
+        delayedReply = NULL;
+        writeForwardedReply(reply.getRaw());
+        return; // do not completeDataDownload() after an earlier response
     }
 
-    completeDataExchange();
+    if (master->serverState != fssHandleDataRequest)
+        return;
+
+    // completeDataDownload() could be waitingForOrigin in fssHandleDataRequest
+    // Depending on which side has finished downloading first, either trust
+    // master->userDataDone status or set originDataDownloadAbortedOnError:
+    if (master->userDataDone) {
+        // We finished downloading before Ftp::Client. Most likely, the
+        // adaptation shortened the origin response or we hit an error.
+        // Our status (stored in master->userDataDone) is more informative.
+        // Use master->userDataDone; avoid originDataDownloadAbortedOnError.
+        completeDataDownload();
+    } else {
+        debugs(33, 5, "too early to write the response");
+        // Ftp::Client naturally finished downloading before us. Set
+        // originDataDownloadAbortedOnError to overwrite future
+        // master->userDataDone and relay Ftp::Client error, if there was
+        // any, to the user.
+        originDataDownloadAbortedOnError = (originStatus >= 400);
+    }
 }
 
 void Ftp::Server::userDataCompletionCheckpoint(int finalStatusCode)
@@ -1723,23 +1760,24 @@
     if (in.bodyParser)
         finishDechunkingRequest(false);
 
-    // The origin control connection is gone, nothing to wait for
-    if (!Comm::IsConnOpen(pinning.serverConnection))
-        master->waitForOriginData = false;
-
-    if (master->waitForOriginData) {
-        // The completeDataExchange() is not called here unconditionally
+    if (waitingForOrigin) {
+        // The completeDataDownload() is not called here unconditionally
         // because we want to signal the FTP user that we are not fully
         // done processing its data stream, even though all data bytes
         // have been sent or received already.
-        debugs(33, 5, "Transfering from/to FTP server is not complete");
+        debugs(33, 5, "Transfering from FTP server is not complete");
         return;
     }
 
-    completeDataExchange();
+    // Adjust our reply if the server aborted with an error before we are done.
+    if (master->userDataDone == 226 && originDataDownloadAbortedOnError) {
+        debugs(33, 5, "Transfering from FTP server terminated with an error, adjust status code");
+        master->userDataDone = 451;
+    }
+    completeDataDownload();
 }
 
-void Ftp::Server::completeDataExchange()
+void Ftp::Server::completeDataDownload()
 {
     writeCustomReply(master->userDataDone, master->userDataDone == 226 ? "Transfer complete" : "Server error; transfer aborted");
     closeDataConnection();
diff -u -r -N squid-3.5.15/src/servers/FtpServer.h squid-3.5.16/src/servers/FtpServer.h
--- squid-3.5.15/src/servers/FtpServer.h	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/servers/FtpServer.h	2016-04-02 10:02:59.000000000 +1300
@@ -41,7 +41,7 @@
 public:
     typedef RefCount<MasterState> Pointer;
 
-    MasterState(): serverState(fssBegin), clientReadGreeting(false), userDataDone(0), waitForOriginData(false) {}
+    MasterState(): serverState(fssBegin), clientReadGreeting(false), userDataDone(0) {}
 
     Ip::Address clientDataAddr; ///< address of our FTP client data connection
     SBuf workingDir; ///< estimated current working directory for URI formation
@@ -49,8 +49,6 @@
     bool clientReadGreeting; ///< whether our FTP client read their FTP server greeting
     /// Squid will send or has sent this final status code to the FTP client
     int userDataDone;
-    /// whether the transfer on the Squid-origin data connection is not over yet
-    bool waitForOriginData;
 };
 
 /// Manages a control connection from an FTP client.
@@ -62,10 +60,14 @@
     /* AsyncJob API */
     virtual void callException(const std::exception &e);
 
+    /// Called by Ftp::Client class when it is start receiving or
+    /// sending data.
+    void startWaitingForOrigin();
+
     /// Called by Ftp::Client class when it is done receiving or
     /// sending data. Waits for both agents to be done before
     /// responding to the FTP client and closing the data connection.
-    void originDataCompletionCheckpoint();
+    void stopWaitingForOrigin(int status);
 
     // This is a pointer in hope to minimize future changes when MasterState
     // becomes a part of MasterXaction. Guaranteed not to be nil.
@@ -121,7 +123,7 @@
 
     /// Writes the data-transfer status reply to the FTP client and
     /// closes the data connection.
-    void completeDataExchange();
+    void completeDataDownload();
 
     void calcUri(const SBuf *file);
     void changeState(const Ftp::ServerState newState, const char *reason);
@@ -186,6 +188,14 @@
     AsyncCall::Pointer connector; ///< set when we are actively connecting
     AsyncCall::Pointer reader; ///< set when we are reading FTP data
 
+    /// whether we wait for the origin data transfer to end
+    bool waitingForOrigin;
+    /// whether the origin data transfer aborted
+    bool originDataDownloadAbortedOnError;
+
+    /// a response which writing was postponed until stopWaitingForOrigin()
+    HttpReply::Pointer delayedReply;
+
     CBDATA_CLASS2(Server);
 };
 
diff -u -r -N squid-3.5.15/src/ssl/helper.cc squid-3.5.16/src/ssl/helper.cc
--- squid-3.5.15/src/ssl/helper.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/ssl/helper.cc	2016-04-02 10:02:59.000000000 +1300
@@ -243,7 +243,8 @@
     if (Ssl::CertValidationHelper::HelperCache &&
             (validationResponse->resultCode == ::Helper::Okay || validationResponse->resultCode == ::Helper::Error)) {
         Ssl::CertValidationResponse::Pointer *item = new Ssl::CertValidationResponse::Pointer(validationResponse);
-        Ssl::CertValidationHelper::HelperCache->add(crtdvdData->query.c_str(), item);
+        if (!Ssl::CertValidationHelper::HelperCache->add(crtdvdData->query.c_str(), item))
+            delete item;
     }
 
     SSL_free(crtdvdData->ssl);
diff -u -r -N squid-3.5.15/src/store.cc squid-3.5.16/src/store.cc
--- squid-3.5.15/src/store.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/store.cc	2016-04-02 10:02:59.000000000 +1300
@@ -34,7 +34,6 @@
 #include "Store.h"
 #include "store_digest.h"
 #include "store_key_md5.h"
-#include "store_key_md5.h"
 #include "store_log.h"
 #include "store_rebuild.h"
 #include "StoreClient.h"
@@ -684,31 +683,27 @@
     if (mem_obj->request) {
         HttpRequest *request = mem_obj->request;
 
-        if (!mem_obj->vary_headers) {
+        if (mem_obj->vary_headers.isEmpty()) {
             /* First handle the case where the object no longer varies */
-            safe_free(request->vary_headers);
+            request->vary_headers.clear();
         } else {
-            if (request->vary_headers && strcmp(request->vary_headers, mem_obj->vary_headers) != 0) {
+            if (!request->vary_headers.isEmpty() && request->vary_headers.cmp(mem_obj->vary_headers) != 0) {
                 /* Oops.. the variance has changed. Kill the base object
                  * to record the new variance key
                  */
-                safe_free(request->vary_headers);       /* free old "bad" variance key */
+                request->vary_headers.clear();       /* free old "bad" variance key */
                 if (StoreEntry *pe = storeGetPublic(mem_obj->storeId(), mem_obj->method))
                     pe->release();
             }
 
             /* Make sure the request knows the variance status */
-            if (!request->vary_headers) {
-                const char *vary = httpMakeVaryMark(request, mem_obj->getReply());
-
-                if (vary)
-                    request->vary_headers = xstrdup(vary);
-            }
+            if (request->vary_headers.isEmpty())
+                request->vary_headers = httpMakeVaryMark(request, mem_obj->getReply());
         }
 
         // TODO: storeGetPublic() calls below may create unlocked entries.
         // We should add/use storeHas() API or lock/unlock those entries.
-        if (mem_obj->vary_headers && !storeGetPublic(mem_obj->storeId(), mem_obj->method)) {
+        if (!mem_obj->vary_headers.isEmpty() && !storeGetPublic(mem_obj->storeId(), mem_obj->method)) {
             /* Create "vary" base object */
             String vary;
             StoreEntry *pe = storeCreateEntry(mem_obj->storeId(), mem_obj->logUri(), request->flags, request->method);
diff -u -r -N squid-3.5.15/src/store_key_md5.cc squid-3.5.16/src/store_key_md5.cc
--- squid-3.5.15/src/store_key_md5.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/store_key_md5.cc	2016-04-02 10:02:59.000000000 +1300
@@ -125,8 +125,8 @@
     SquidMD5Update(&M, &m, sizeof(m));
     SquidMD5Update(&M, (unsigned char *) url, strlen(url));
 
-    if (request->vary_headers) {
-        SquidMD5Update(&M, (unsigned char *) request->vary_headers, strlen(request->vary_headers));
+    if (!request->vary_headers.isEmpty()) {
+        SquidMD5Update(&M, request->vary_headers.rawContent(), request->vary_headers.length());
         debugs(20, 3, "updating public key by vary headers: " << request->vary_headers << " for: " << url);
     }
 
diff -u -r -N squid-3.5.15/src/StoreMetaVary.cc squid-3.5.16/src/StoreMetaVary.cc
--- squid-3.5.15/src/StoreMetaVary.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/StoreMetaVary.cc	2016-04-02 10:02:59.000000000 +1300
@@ -18,14 +18,14 @@
 {
     assert (getType() == STORE_META_VARY_HEADERS);
 
-    if (!e->mem_obj->vary_headers) {
+    if (e->mem_obj->vary_headers.isEmpty()) {
         /* XXX separate this mutator from the query */
         /* Assume the object is OK.. remember the vary request headers */
-        e->mem_obj->vary_headers = xstrdup((char *)value);
+        e->mem_obj->vary_headers.assign(static_cast<const char *>(value), length);
         return true;
     }
 
-    if (strcmp(e->mem_obj->vary_headers, (char *)value) != 0)
+    if (e->mem_obj->vary_headers.cmp(static_cast<const char *>(value), length) != 0)
         return false;
 
     return true;
diff -u -r -N squid-3.5.15/src/store_swapmeta.cc squid-3.5.16/src/store_swapmeta.cc
--- squid-3.5.15/src/store_swapmeta.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/store_swapmeta.cc	2016-04-02 10:02:59.000000000 +1300
@@ -40,7 +40,6 @@
     tlv *TLV = NULL;        /* we'll return this */
     tlv **T = &TLV;
     const char *url;
-    const char *vary;
     assert(e->mem_obj != NULL);
     const int64_t objsize = e->mem_obj->expectedReplySize();
     assert(e->swap_status == SWAPOUT_WRITING);
@@ -87,10 +86,12 @@
     }
 
     T = StoreMeta::Add(T, t);
-    vary = e->mem_obj->vary_headers;
+    SBuf vary(e->mem_obj->vary_headers);
 
-    if (vary) {
-        t =StoreMeta::Factory(STORE_META_VARY_HEADERS, strlen(vary) + 1, vary);
+    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());
 
         if (!t) {
             storeSwapTLVFree(TLV);
diff -u -r -N squid-3.5.15/src/tests/stub_comm.cc squid-3.5.16/src/tests/stub_comm.cc
--- squid-3.5.15/src/tests/stub_comm.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/tests/stub_comm.cc	2016-04-02 10:02:59.000000000 +1300
@@ -57,7 +57,7 @@
 int ignoreErrno(int ierrno) STUB_RETVAL(-1)
 void commCloseAllSockets(void) STUB
 void checkTimeouts(void) STUB
-void comm_add_close_handler(int fd, CLCB *, void *) STUB
+AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *, void *) STUB
 void comm_add_close_handler(int fd, AsyncCall::Pointer &) STUB
 void comm_remove_close_handler(int fd, CLCB *, void *) STUB
 void comm_remove_close_handler(int fd, AsyncCall::Pointer &)STUB
diff -u -r -N squid-3.5.15/src/tests/stub_http.cc squid-3.5.16/src/tests/stub_http.cc
--- squid-3.5.15/src/tests/stub_http.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/tests/stub_http.cc	2016-04-02 10:02:59.000000000 +1300
@@ -7,12 +7,12 @@
  */
 
 #include "squid.h"
-
 #include "HttpReply.h"
 #include "HttpRequest.h"
+#include "SBuf.h"
 
 #define STUB_API "http.cc"
 #include "tests/STUB.h"
 
-const char * httpMakeVaryMark(HttpRequest * request, HttpReply const * reply) STUB_RETVAL(NULL)
+SBuf httpMakeVaryMark(HttpRequest *, HttpReply const *) STUB_RETVAL(SBuf())
 
diff -u -r -N squid-3.5.15/src/tests/stub_MemObject.cc squid-3.5.16/src/tests/stub_MemObject.cc
--- squid-3.5.15/src/tests/stub_MemObject.cc	2016-02-24 05:25:46.000000000 +1300
+++ squid-3.5.16/src/tests/stub_MemObject.cc	2016-04-02 10:02:59.000000000 +1300
@@ -38,7 +38,6 @@
     id(0),
     object_sz(-1),
     swap_hdr_sz(0),
-    vary_headers(NULL),
     _reply(NULL)
 {
     memset(&clients, 0, sizeof(clients));
