]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
5.2 (#907) SQUID_5_2
authorsquidadm <squidadm@users.noreply.github.com>
Sun, 3 Oct 2021 15:07:36 +0000 (04:07 +1300)
committerGitHub <noreply@github.com>
Sun, 3 Oct 2021 15:07:36 +0000 (04:07 +1300)
ChangeLog
configure.ac
doc/release-notes/release-4.sgml
doc/release-notes/release-5.sgml
src/clients/FtpGateway.cc
src/wccp2.cc

index 555876188c99cf8d05a9625671d0ecfe9ac0b849..1b16b02b964ef61f2efaec90d0fc350355c60d19 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Changes in squid-5.2 (03 Oct 2021):
+
+       - Bug 5164: a copy-paste typo in HttpHdrCc::hasMinFresh()
+       - Bug 4922: Improve ftp://... filename extraction
+       - TLS: Fix X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY handling
+       - ... and all fixes from 4.17
+
 Changes in squid-5.1 (01 Aug 2021):
 
        - Bug 4696: Fix leaky String move assignment operator
@@ -120,6 +127,10 @@ Changes in squid-5.0.1 (14 Jan 2020):
        - ... and much code cleanup and polishing
        - ... and all fixes from 4.10
 
+Changes in squid-4.17 (03 Oct 2021):
+
+       - WCCP: Validate packets better
+
 Changes in squid-4.16 (04 Jul 2021):
 
        - Regression Fix: --with-valgrind-debug build broken since 4.15
index ffb4f1024d5b8b8bdd0f3056892cae309511c529..7bf6a0521b36d72d09429082d6e9916a86d8d31c 100644 (file)
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[5.1-VCS],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[5.2-VCS],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
index 0130a695baf462c510de0638962ba5730d72dd32..74018725b4a6dbb26ca2032aa2ad697aaa911776 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype linuxdoc system>
 <article>
-<title>Squid 4.16 release notes</title>
+<title>Squid 4.17 release notes</title>
 <author>Squid Developers</author>
 
 <abstract>
@@ -12,7 +12,7 @@ for Applied Network Research and members of the Web Caching community.
 <toc>
 
 <sect>Notice
-<p>The Squid Team are pleased to announce the release of Squid-4.16.
+<p>The Squid Team are pleased to announce the release of Squid-4.17.
 
 This new release is available for download from <url url="http://www.squid-cache.org/Versions/v4/"> or the
  <url url="http://www.squid-cache.org/Download/http-mirrors.html" name="mirrors">.
index 80a0a2d3253bb0e49a14fdd94233cdbdc7c3a015..efc9c3eb0cc8228533b38f1451cb493efa8a55d6 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype linuxdoc system>
 <article>
-<title>Squid 5.1 release notes</title>
+<title>Squid 5.2 release notes</title>
 <author>Squid Developers</author>
 
 <abstract>
@@ -12,7 +12,7 @@ for Applied Network Research and members of the Web Caching community.
 <toc>
 
 <sect>Notice
-<p>The Squid Team are pleased to announce the release of Squid-5.1.
+<p>The Squid Team are pleased to announce the release of Squid-5.2.
 
 This new release is available for download from <url url="http://www.squid-cache.org/Versions/v5/"> or the
  <url url="http://www.squid-cache.org/Download/http-mirrors.html" name="mirrors">.
index 3033ae889e9c3d22c66916cc699d506b119e8cca..bd1665ea75c2ef738a8c7240b9107af5ea4c2a60 100644 (file)
@@ -1081,7 +1081,7 @@ Ftp::Gateway::checkUrlpath()
         const auto fullPath = request->url.path();
         const auto typecodePos = typeSpecStart + middle.length();
         typecode = (typecodePos < fullPath.length()) ?
-            static_cast<char>(xtoupper(fullPath[typecodePos])) : '\0';
+                   static_cast<char>(xtoupper(fullPath[typecodePos])) : '\0';
         request->url.path(fullPath.substr(0, typeSpecStart));
     }
 
index 9dad778171ac8b06e4156281ed98dd3ed267580f..5a4a15a7ba7707d5ede3a0c77cbe4c95aa7019a1 100644 (file)
@@ -1224,344 +1224,344 @@ wccp2HandleUdp(int sock, void *)
         Must3(ntohs(wccp2_i_see_you.version) == WCCP2_VERSION, "WCCP version unsupported", Here());
         Must3(ntohl(wccp2_i_see_you.type) == WCCP2_I_SEE_YOU, "WCCP packet type unsupported", Here());
 
-    // XXX: drop conversion boundary
-    from_tmp.getSockAddr(from);
+        // XXX: drop conversion boundary
+        from_tmp.getSockAddr(from);
 
-    debugs(80, 3, "Incoming WCCPv2 I_SEE_YOU length " << ntohs(wccp2_i_see_you.length) << ".");
+        debugs(80, 3, "Incoming WCCPv2 I_SEE_YOU length " << ntohs(wccp2_i_see_you.length) << ".");
 
-    /* Record the total data length */
-    const auto data_length = ntohs(wccp2_i_see_you.length);
-    Must3(data_length <= len - message_header_size,
-          "malformed packet claiming it's bigger than received data", Here());
+        /* Record the total data length */
+        const auto data_length = ntohs(wccp2_i_see_you.length);
+        Must3(data_length <= len - message_header_size,
+              "malformed packet claiming it's bigger than received data", Here());
 
-    size_t offset = 0;
+        size_t offset = 0;
 
-    /* Go through the data structure */
-    while (offset + sizeof(struct wccp2_item_header_t) <= data_length) {
+        /* Go through the data structure */
+        while (offset + sizeof(struct wccp2_item_header_t) <= data_length) {
 
-        char *data = wccp2_i_see_you.data;
+            char *data = wccp2_i_see_you.data;
 
-        const auto itemHeader = reinterpret_cast<const wccp2_item_header_t*>(&data[offset]);
-        const auto itemSize = CheckFieldDataLength(itemHeader, ntohs(itemHeader->length),
-                              data, data_length, "truncated record");
-        // XXX: Check "The specified length must be a multiple of 4 octets"
-        // requirement to avoid unaligned memory reads after the first item.
+            const auto itemHeader = reinterpret_cast<const wccp2_item_header_t*>(&data[offset]);
+            const auto itemSize = CheckFieldDataLength(itemHeader, ntohs(itemHeader->length),
+                                  data, data_length, "truncated record");
+            // XXX: Check "The specified length must be a multiple of 4 octets"
+            // requirement to avoid unaligned memory reads after the first item.
 
-        switch (ntohs(itemHeader->type)) {
+            switch (ntohs(itemHeader->type)) {
 
-        case WCCP2_SECURITY_INFO:
-            Must3(!security_info, "duplicate security definition", Here());
-            SetField(security_info, itemHeader, itemHeader, itemSize,
-                     "security definition truncated");
-            break;
+            case WCCP2_SECURITY_INFO:
+                Must3(!security_info, "duplicate security definition", Here());
+                SetField(security_info, itemHeader, itemHeader, itemSize,
+                         "security definition truncated");
+                break;
 
-        case WCCP2_SERVICE_INFO:
-            Must3(!service_info, "duplicate service_info definition", Here());
-            SetField(service_info, itemHeader, itemHeader, itemSize,
-                     "service_info definition truncated");
-            break;
+            case WCCP2_SERVICE_INFO:
+                Must3(!service_info, "duplicate service_info definition", Here());
+                SetField(service_info, itemHeader, itemHeader, itemSize,
+                         "service_info definition truncated");
+                break;
 
-        case WCCP2_ROUTER_ID_INFO:
-            Must3(!router_identity_info, "duplicate router_identity_info definition", Here());
-            SetField(router_identity_info, itemHeader, itemHeader, itemSize,
-                     "router_identity_info definition truncated");
-            break;
+            case WCCP2_ROUTER_ID_INFO:
+                Must3(!router_identity_info, "duplicate router_identity_info definition", Here());
+                SetField(router_identity_info, itemHeader, itemHeader, itemSize,
+                         "router_identity_info definition truncated");
+                break;
 
-        case WCCP2_RTR_VIEW_INFO:
-            Must3(!router_view_header, "duplicate router_view definition", Here());
-            SetField(router_view_header, itemHeader, itemHeader, itemSize,
-                     "router_view definition truncated");
-            break;
+            case WCCP2_RTR_VIEW_INFO:
+                Must3(!router_view_header, "duplicate router_view definition", Here());
+                SetField(router_view_header, itemHeader, itemHeader, itemSize,
+                         "router_view definition truncated");
+                break;
 
-        case WCCP2_CAPABILITY_INFO: {
-            Must3(!router_capability_header, "duplicate router_capability definition", Here());
-            SetField(router_capability_header, itemHeader, itemHeader, itemSize,
-                     "router_capability definition truncated");
+            case WCCP2_CAPABILITY_INFO: {
+                Must3(!router_capability_header, "duplicate router_capability definition", Here());
+                SetField(router_capability_header, itemHeader, itemHeader, itemSize,
+                         "router_capability definition truncated");
 
-            CheckFieldDataLength(router_capability_header, ntohs(router_capability_header->capability_info_length),
-                                 itemHeader, itemSize, "capability info truncated");
-            router_capability_data_start = reinterpret_cast<char*>(router_capability_header) +
-                                           sizeof(*router_capability_header);
-            break;
-        }
+                CheckFieldDataLength(router_capability_header, ntohs(router_capability_header->capability_info_length),
+                                     itemHeader, itemSize, "capability info truncated");
+                router_capability_data_start = reinterpret_cast<char*>(router_capability_header) +
+                                               sizeof(*router_capability_header);
+                break;
+            }
 
-        /* Nothing to do for the types below */
+            /* Nothing to do for the types below */
 
-        case WCCP2_ASSIGN_MAP:
-        case WCCP2_REDIRECT_ASSIGNMENT:
-            break;
+            case WCCP2_ASSIGN_MAP:
+            case WCCP2_REDIRECT_ASSIGNMENT:
+                break;
 
-        default:
-            debugs(80, DBG_IMPORTANT, "Unknown record type in WCCPv2 Packet (" << ntohs(itemHeader->type) << ").");
+            default:
+                debugs(80, DBG_IMPORTANT, "Unknown record type in WCCPv2 Packet (" << ntohs(itemHeader->type) << ").");
+            }
+
+            offset += itemSize;
+            assert(offset <= data_length && "CheckFieldDataLength(itemHeader...) established that");
         }
 
-        offset += itemSize;
-        assert(offset <= data_length && "CheckFieldDataLength(itemHeader...) established that");
-    }
+        Must3(security_info, "packet missing security definition", Here());
+        Must3(service_info, "packet missing service_info definition", Here());
+        Must3(router_identity_info, "packet missing router_identity_info definition", Here());
+        Must3(router_view_header, "packet missing router_view definition", Here());
 
-    Must3(security_info, "packet missing security definition", Here());
-    Must3(service_info, "packet missing service_info definition", Here());
-    Must3(router_identity_info, "packet missing router_identity_info definition", Here());
-    Must3(router_view_header, "packet missing router_view definition", Here());
+        debugs(80, 5, "Complete packet received");
 
-    debugs(80, 5, "Complete packet received");
+        /* Check that the service in the packet is configured on this router */
+        service_list_ptr = wccp2_service_list_head;
 
-    /* Check that the service in the packet is configured on this router */
-    service_list_ptr = wccp2_service_list_head;
+        while (service_list_ptr != NULL) {
+            if (service_info->service_id == service_list_ptr->service_info->service_id) {
+                break;
+            }
 
-    while (service_list_ptr != NULL) {
-        if (service_info->service_id == service_list_ptr->service_info->service_id) {
-            break;
+            service_list_ptr = service_list_ptr->next;
         }
 
-        service_list_ptr = service_list_ptr->next;
-    }
+        if (service_list_ptr == NULL) {
+            debugs(80, DBG_IMPORTANT, "WCCPv2 Unknown service received from router (" << service_info->service_id << ")");
+            return;
+        }
 
-    if (service_list_ptr == NULL) {
-        debugs(80, DBG_IMPORTANT, "WCCPv2 Unknown service received from router (" << service_info->service_id << ")");
-        return;
-    }
+        if (ntohl(security_info->security_option) != ntohl(service_list_ptr->security_info->security_option)) {
+            debugs(80, DBG_IMPORTANT, "Invalid security option in WCCPv2 Packet (" << ntohl(security_info->security_option) << " vs " << ntohl(service_list_ptr->security_info->security_option) << ").");
+            return;
+        }
 
-    if (ntohl(security_info->security_option) != ntohl(service_list_ptr->security_info->security_option)) {
-        debugs(80, DBG_IMPORTANT, "Invalid security option in WCCPv2 Packet (" << ntohl(security_info->security_option) << " vs " << ntohl(service_list_ptr->security_info->security_option) << ").");
-        return;
-    }
+        if (!wccp2_check_security(service_list_ptr, (char *) security_info, (char *) &wccp2_i_see_you, len)) {
+            debugs(80, DBG_IMPORTANT, "Received WCCPv2 Packet failed authentication");
+            return;
+        }
 
-    if (!wccp2_check_security(service_list_ptr, (char *) security_info, (char *) &wccp2_i_see_you, len)) {
-        debugs(80, DBG_IMPORTANT, "Received WCCPv2 Packet failed authentication");
-        return;
-    }
+        /* Check that the router address is configured on this router */
+        for (router_list_ptr = &service_list_ptr->router_list_head; router_list_ptr->next != NULL; router_list_ptr = router_list_ptr->next) {
+            if (router_list_ptr->router_sendto_address.s_addr == from.sin_addr.s_addr)
+                break;
+        }
 
-    /* Check that the router address is configured on this router */
-    for (router_list_ptr = &service_list_ptr->router_list_head; router_list_ptr->next != NULL; router_list_ptr = router_list_ptr->next) {
-        if (router_list_ptr->router_sendto_address.s_addr == from.sin_addr.s_addr)
-            break;
-    }
+        Must3(router_list_ptr->next, "packet received from unknown router", Here());
 
-    Must3(router_list_ptr->next, "packet received from unknown router", Here());
+        /* Set the router id */
+        router_list_ptr->info->router_address = router_identity_info->router_id_element.router_address;
 
-    /* Set the router id */
-    router_list_ptr->info->router_address = router_identity_info->router_id_element.router_address;
+        /* Increment the received id in the packet */
+        if (ntohl(router_list_ptr->info->received_id) != ntohl(router_identity_info->router_id_element.received_id)) {
+            debugs(80, 3, "Incoming WCCP2_I_SEE_YOU Received ID old=" << ntohl(router_list_ptr->info->received_id) << " new=" << ntohl(router_identity_info->router_id_element.received_id) << ".");
+            router_list_ptr->info->received_id = router_identity_info->router_id_element.received_id;
+        }
 
-    /* Increment the received id in the packet */
-    if (ntohl(router_list_ptr->info->received_id) != ntohl(router_identity_info->router_id_element.received_id)) {
-        debugs(80, 3, "Incoming WCCP2_I_SEE_YOU Received ID old=" << ntohl(router_list_ptr->info->received_id) << " new=" << ntohl(router_identity_info->router_id_element.received_id) << ".");
-        router_list_ptr->info->received_id = router_identity_info->router_id_element.received_id;
-    }
+        /* TODO: check return/forwarding methods */
+        if (router_capability_header == NULL) {
+            if ((Config.Wccp2.return_method != WCCP2_PACKET_RETURN_METHOD_GRE) || (Config.Wccp2.forwarding_method != WCCP2_FORWARDING_METHOD_GRE)) {
+                debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router does not support the forwarding method specified, only GRE supported");
+                wccp2ConnectionClose();
+                return;
+            }
+        } else {
 
-    /* TODO: check return/forwarding methods */
-    if (router_capability_header == NULL) {
-        if ((Config.Wccp2.return_method != WCCP2_PACKET_RETURN_METHOD_GRE) || (Config.Wccp2.forwarding_method != WCCP2_FORWARDING_METHOD_GRE)) {
-            debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router does not support the forwarding method specified, only GRE supported");
-            wccp2ConnectionClose();
-            return;
-        }
-    } else {
+            const auto router_capability_data_length = ntohs(router_capability_header->capability_info_length);
+            assert(router_capability_data_start);
+            const auto router_capability_data_end = router_capability_data_start +
+                                                    router_capability_data_length;
+            for (auto router_capability_data_current = router_capability_data_start;
+                    router_capability_data_current < router_capability_data_end;) {
+
+                SetField(router_capability_element, router_capability_data_current,
+                         router_capability_data_start, router_capability_data_length,
+                         "capability element header truncated");
+                const auto elementSize = CheckFieldDataLength(
+                                             router_capability_element, ntohs(router_capability_element->capability_length),
+                                             router_capability_data_start, router_capability_data_length,
+                                             "capability element truncated");
+
+                switch (ntohs(router_capability_element->capability_type)) {
+
+                case WCCP2_CAPABILITY_FORWARDING_METHOD:
+
+                    if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.forwarding_method)) {
+                        debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different forwarding method " << ntohl(router_capability_element->capability_value) << ", expected " << Config.Wccp2.forwarding_method);
+                        wccp2ConnectionClose();
+                        return;
+                    }
 
-        const auto router_capability_data_length = ntohs(router_capability_header->capability_info_length);
-        assert(router_capability_data_start);
-        const auto router_capability_data_end = router_capability_data_start +
-                                                router_capability_data_length;
-        for (auto router_capability_data_current = router_capability_data_start;
-                router_capability_data_current < router_capability_data_end;) {
-
-            SetField(router_capability_element, router_capability_data_current,
-                     router_capability_data_start, router_capability_data_length,
-                     "capability element header truncated");
-            const auto elementSize = CheckFieldDataLength(
-                                         router_capability_element, ntohs(router_capability_element->capability_length),
-                                         router_capability_data_start, router_capability_data_length,
-                                         "capability element truncated");
-
-            switch (ntohs(router_capability_element->capability_type)) {
-
-            case WCCP2_CAPABILITY_FORWARDING_METHOD:
-
-                if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.forwarding_method)) {
-                    debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different forwarding method " << ntohl(router_capability_element->capability_value) << ", expected " << Config.Wccp2.forwarding_method);
-                    wccp2ConnectionClose();
-                    return;
-                }
+                    break;
 
-                break;
+                case WCCP2_CAPABILITY_ASSIGNMENT_METHOD:
 
-            case WCCP2_CAPABILITY_ASSIGNMENT_METHOD:
+                    if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.assignment_method)) {
+                        debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different assignment method " << ntohl(router_capability_element->capability_value) << ", expected "<< Config.Wccp2.assignment_method);
+                        wccp2ConnectionClose();
+                        return;
+                    }
 
-                if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.assignment_method)) {
-                    debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different assignment method " << ntohl(router_capability_element->capability_value) << ", expected "<< Config.Wccp2.assignment_method);
-                    wccp2ConnectionClose();
-                    return;
-                }
+                    break;
 
-                break;
+                case WCCP2_CAPABILITY_RETURN_METHOD:
 
-            case WCCP2_CAPABILITY_RETURN_METHOD:
+                    if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.return_method)) {
+                        debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different return method " << ntohl(router_capability_element->capability_value) << ", expected " << Config.Wccp2.return_method);
+                        wccp2ConnectionClose();
+                        return;
+                    }
 
-                if (!(ntohl(router_capability_element->capability_value) & Config.Wccp2.return_method)) {
-                    debugs(80, DBG_IMPORTANT, "wccp2HandleUdp: fatal error - A WCCP router has specified a different return method " << ntohl(router_capability_element->capability_value) << ", expected " << Config.Wccp2.return_method);
-                    wccp2ConnectionClose();
-                    return;
-                }
+                    break;
 
-                break;
+                case 4:
+                case 5:
+                    break; // ignore silently for now
 
-            case 4:
-            case 5:
-                break; // ignore silently for now
+                default:
+                    debugs(80, DBG_IMPORTANT, "Unknown capability type in WCCPv2 Packet (" << ntohs(router_capability_element->capability_type) << ").");
+                }
 
-            default:
-                debugs(80, DBG_IMPORTANT, "Unknown capability type in WCCPv2 Packet (" << ntohs(router_capability_element->capability_type) << ").");
+                router_capability_data_current += elementSize;
             }
-
-            router_capability_data_current += elementSize;
         }
-    }
 
-    debugs(80, 5, "Cleaning out cache list");
-    /* clean out the old cache list */
+        debugs(80, 5, "Cleaning out cache list");
+        /* clean out the old cache list */
 
-    for (cache_list_ptr = &router_list_ptr->cache_list_head; cache_list_ptr; cache_list_ptr = cache_list_ptr_next) {
-        cache_list_ptr_next = cache_list_ptr->next;
+        for (cache_list_ptr = &router_list_ptr->cache_list_head; cache_list_ptr; cache_list_ptr = cache_list_ptr_next) {
+            cache_list_ptr_next = cache_list_ptr->next;
 
-        if (cache_list_ptr != &router_list_ptr->cache_list_head) {
-            xfree(cache_list_ptr);
+            if (cache_list_ptr != &router_list_ptr->cache_list_head) {
+                xfree(cache_list_ptr);
+            }
         }
-    }
 
-    router_list_ptr->num_caches = htonl(0);
-    num_caches = 0;
+        router_list_ptr->num_caches = htonl(0);
+        num_caches = 0;
 
-    /* Check to see if we're the master cache and update the cache list */
-    bool found = false;
-    service_list_ptr->lowest_ip = 1;
-    cache_list_ptr = &router_list_ptr->cache_list_head;
+        /* Check to see if we're the master cache and update the cache list */
+        bool found = false;
+        service_list_ptr->lowest_ip = 1;
+        cache_list_ptr = &router_list_ptr->cache_list_head;
 
-    /* to find the list of caches, we start at the end of the router view header */
+        /* to find the list of caches, we start at the end of the router view header */
 
-    ptr = (char *) (router_view_header) + sizeof(struct router_view_t);
-    const auto router_view_size = sizeof(struct router_view_t) +
-                                  ntohs(router_view_header->header.length);
+        ptr = (char *) (router_view_header) + sizeof(struct router_view_t);
+        const auto router_view_size = sizeof(struct router_view_t) +
+                                      ntohs(router_view_header->header.length);
 
-    /* Then we read the number of routers */
-    const uint32_t *routerCountRaw = nullptr;
-    SetField(routerCountRaw, ptr, router_view_header, router_view_size,
-             "malformed packet (truncated router view info w/o number of routers)");
+        /* Then we read the number of routers */
+        const uint32_t *routerCountRaw = nullptr;
+        SetField(routerCountRaw, ptr, router_view_header, router_view_size,
+                 "malformed packet (truncated router view info w/o number of routers)");
 
-    /* skip the number plus all the ip's */
-    ptr += sizeof(*routerCountRaw);
-    const auto ipCount = ntohl(*routerCountRaw);
-    const auto ipsSize = ipCount * sizeof(struct in_addr); // we check for unsigned overflow below
-    Must3(ipsSize / sizeof(struct in_addr) != ipCount, "huge IP address count", Here());
-    CheckSectionLength(ptr, ipsSize, router_view_header, router_view_size, "invalid IP address count");
-    ptr += ipsSize;
+        /* skip the number plus all the ip's */
+        ptr += sizeof(*routerCountRaw);
+        const auto ipCount = ntohl(*routerCountRaw);
+        const auto ipsSize = ipCount * sizeof(struct in_addr); // we check for unsigned overflow below
+        Must3(ipsSize / sizeof(struct in_addr) != ipCount, "huge IP address count", Here());
+        CheckSectionLength(ptr, ipsSize, router_view_header, router_view_size, "invalid IP address count");
+        ptr += ipsSize;
 
-    /* Then read the number of caches */
-    const uint32_t *cacheCountRaw = nullptr;
-    SetField(cacheCountRaw, ptr, router_view_header, router_view_size,
-             "malformed packet (truncated router view info w/o cache count)");
-    memcpy(&tmp, cacheCountRaw, sizeof(tmp)); // TODO: Replace tmp with cacheCount
-    ptr += sizeof(tmp);
+        /* Then read the number of caches */
+        const uint32_t *cacheCountRaw = nullptr;
+        SetField(cacheCountRaw, ptr, router_view_header, router_view_size,
+                 "malformed packet (truncated router view info w/o cache count)");
+        memcpy(&tmp, cacheCountRaw, sizeof(tmp)); // TODO: Replace tmp with cacheCount
+        ptr += sizeof(tmp);
 
-    if (ntohl(tmp) != 0) {
-        /* search through the list of received-from ip addresses */
+        if (ntohl(tmp) != 0) {
+            /* search through the list of received-from ip addresses */
 
-        for (num_caches = 0; num_caches < (int) ntohl(tmp); ++num_caches) {
-            /* Get a copy of the ip */
-            memset(&cache_address, 0, sizeof(cache_address)); // Make GCC happy
+            for (num_caches = 0; num_caches < (int) ntohl(tmp); ++num_caches) {
+                /* Get a copy of the ip */
+                memset(&cache_address, 0, sizeof(cache_address)); // Make GCC happy
 
-            switch (Config.Wccp2.assignment_method) {
+                switch (Config.Wccp2.assignment_method) {
 
-            case WCCP2_ASSIGNMENT_METHOD_HASH:
+                case WCCP2_ASSIGNMENT_METHOD_HASH:
 
-                SetField(cache_identity, ptr, router_view_header, router_view_size,
-                         "malformed packet (truncated router view info cache w/o assignment hash)");
+                    SetField(cache_identity, ptr, router_view_header, router_view_size,
+                             "malformed packet (truncated router view info cache w/o assignment hash)");
 
-                ptr += sizeof(struct wccp2_cache_identity_info_t);
+                    ptr += sizeof(struct wccp2_cache_identity_info_t);
 
-                memcpy(&cache_address, &cache_identity->addr, sizeof(struct in_addr));
+                    memcpy(&cache_address, &cache_identity->addr, sizeof(struct in_addr));
 
-                cache_list_ptr->weight = ntohs(cache_identity->weight);
-                break;
+                    cache_list_ptr->weight = ntohs(cache_identity->weight);
+                    break;
 
-            case WCCP2_ASSIGNMENT_METHOD_MASK:
+                case WCCP2_ASSIGNMENT_METHOD_MASK:
 
-                SetField(cache_mask_info, ptr, router_view_header, router_view_size,
-                         "malformed packet (truncated router view info cache w/o assignment mask)");
+                    SetField(cache_mask_info, ptr, router_view_header, router_view_size,
+                             "malformed packet (truncated router view info cache w/o assignment mask)");
 
-                /* The mask assignment has an undocumented variable length entry here */
+                    /* The mask assignment has an undocumented variable length entry here */
 
-                if (ntohl(cache_mask_info->num1) == 3) {
+                    if (ntohl(cache_mask_info->num1) == 3) {
 
-                    SetField(cache_mask_identity, ptr, router_view_header, router_view_size,
-                             "malformed packet (truncated router view info cache w/o assignment mask identity)");
+                        SetField(cache_mask_identity, ptr, router_view_header, router_view_size,
+                                 "malformed packet (truncated router view info cache w/o assignment mask identity)");
 
-                    ptr += sizeof(struct wccp2_cache_mask_identity_info_t);
+                        ptr += sizeof(struct wccp2_cache_mask_identity_info_t);
 
-                    memcpy(&cache_address, &cache_mask_identity->addr, sizeof(struct in_addr));
-                } else {
+                        memcpy(&cache_address, &cache_mask_identity->addr, sizeof(struct in_addr));
+                    } else {
 
-                    ptr += sizeof(struct cache_mask_info_t);
+                        ptr += sizeof(struct cache_mask_info_t);
 
-                    memcpy(&cache_address, &cache_mask_info->addr, sizeof(struct in_addr));
-                }
+                        memcpy(&cache_address, &cache_mask_info->addr, sizeof(struct in_addr));
+                    }
 
-                cache_list_ptr->weight = 0;
-                break;
+                    cache_list_ptr->weight = 0;
+                    break;
 
-            default:
-                fatalf("Unknown Wccp2 assignment method\n");
-            }
+                default:
+                    fatalf("Unknown Wccp2 assignment method\n");
+                }
 
-            /* Update the cache list */
-            cache_list_ptr->cache_ip = cache_address;
+                /* Update the cache list */
+                cache_list_ptr->cache_ip = cache_address;
 
-            cache_list_ptr->next = (wccp2_cache_list_t*) xcalloc(1, sizeof(struct wccp2_cache_list_t));
+                cache_list_ptr->next = (wccp2_cache_list_t*) xcalloc(1, sizeof(struct wccp2_cache_list_t));
 
-            cache_list_ptr = cache_list_ptr->next;
+                cache_list_ptr = cache_list_ptr->next;
 
-            cache_list_ptr->next = NULL;
+                cache_list_ptr->next = NULL;
 
-            debugs (80, 5,  "checking cache list: (" << std::hex << cache_address.s_addr << ":" <<  router_list_ptr->local_ip.s_addr << ")");
+                debugs (80, 5,  "checking cache list: (" << std::hex << cache_address.s_addr << ":" <<  router_list_ptr->local_ip.s_addr << ")");
 
-            /* Check to see if it's the master, or us */
-            found = found || (cache_address.s_addr == router_list_ptr->local_ip.s_addr);
+                /* Check to see if it's the master, or us */
+                found = found || (cache_address.s_addr == router_list_ptr->local_ip.s_addr);
 
-            if (cache_address.s_addr < router_list_ptr->local_ip.s_addr) {
-                service_list_ptr->lowest_ip = 0;
+                if (cache_address.s_addr < router_list_ptr->local_ip.s_addr) {
+                    service_list_ptr->lowest_ip = 0;
+                }
             }
-        }
-    } else {
-        debugs(80, 5, "Adding ourselves as the only cache");
+        } else {
+            debugs(80, 5, "Adding ourselves as the only cache");
 
-        /* Update the cache list */
-        cache_list_ptr->cache_ip = router_list_ptr->local_ip;
+            /* Update the cache list */
+            cache_list_ptr->cache_ip = router_list_ptr->local_ip;
 
-        cache_list_ptr->next = (wccp2_cache_list_t*) xcalloc(1, sizeof(struct wccp2_cache_list_t));
-        cache_list_ptr = cache_list_ptr->next;
-        cache_list_ptr->next = NULL;
+            cache_list_ptr->next = (wccp2_cache_list_t*) xcalloc(1, sizeof(struct wccp2_cache_list_t));
+            cache_list_ptr = cache_list_ptr->next;
+            cache_list_ptr->next = NULL;
 
-        service_list_ptr->lowest_ip = 1;
-        found = true;
-        num_caches = 1;
-    }
+            service_list_ptr->lowest_ip = 1;
+            found = true;
+            num_caches = 1;
+        }
 
-    wccp2SortCacheList(&router_list_ptr->cache_list_head);
+        wccp2SortCacheList(&router_list_ptr->cache_list_head);
 
-    router_list_ptr->num_caches = htonl(num_caches);
+        router_list_ptr->num_caches = htonl(num_caches);
 
-    if (found && (service_list_ptr->lowest_ip == 1)) {
-        if (ntohl(router_view_header->change_number) != router_list_ptr->member_change) {
-            debugs(80, 4, "Change detected - queueing up new assignment");
-            router_list_ptr->member_change = ntohl(router_view_header->change_number);
-            eventDelete(wccp2AssignBuckets, NULL);
-            eventAdd("wccp2AssignBuckets", wccp2AssignBuckets, NULL, 15.0, 1);
+        if (found && (service_list_ptr->lowest_ip == 1)) {
+            if (ntohl(router_view_header->change_number) != router_list_ptr->member_change) {
+                debugs(80, 4, "Change detected - queueing up new assignment");
+                router_list_ptr->member_change = ntohl(router_view_header->change_number);
+                eventDelete(wccp2AssignBuckets, NULL);
+                eventAdd("wccp2AssignBuckets", wccp2AssignBuckets, NULL, 15.0, 1);
+            } else {
+                debugs(80, 5, "Change not detected (" << ntohl(router_view_header->change_number) << " = " << router_list_ptr->member_change << ")");
+            }
         } else {
-            debugs(80, 5, "Change not detected (" << ntohl(router_view_header->change_number) << " = " << router_list_ptr->member_change << ")");
+            eventDelete(wccp2AssignBuckets, NULL);
+            debugs(80, 5, "I am not the lowest ip cache - not assigning buckets");
         }
-    } else {
-        eventDelete(wccp2AssignBuckets, NULL);
-        debugs(80, 5, "I am not the lowest ip cache - not assigning buckets");
-    }
 
     } catch (...) {
         debugs(80, DBG_IMPORTANT, "ERROR: Ignoring WCCPv2 message: " << CurrentException);