]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 2038: check reply_body_max_size before ICAP
authorrousskov <>
Sat, 9 Feb 2008 01:27:59 +0000 (01:27 +0000)
committerrousskov <>
Sat, 9 Feb 2008 01:27:59 +0000 (01:27 +0000)
Moved maxReplyBodySize-related code from ClientHttpRequest to HttpReply
because server-side needs it too to check limits before ICAP sucks all the
data in.

Calculating limit requires knowing HttpRequest because it affects expected
content length. Since I did not find a single place where any HttpReply would
be guaranteed to be given the request to calculate the limit, we now supply
the request whenever a limit check is performed. The limit calculation result
is cached and the calculation should not be repeated.

src/HttpReply.cc
src/HttpReply.h
src/client_side_request.cc
src/client_side_request.h

index e5ae153bec45b2ce2dcd617c10f8a4f5e4ac99b8..ee6718ad623057ae31ed8cf175df11189ab8f633 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpReply.cc,v 1.99 2008/02/03 10:00:29 amosjeffries Exp $
+ * $Id: HttpReply.cc,v 1.100 2008/02/08 18:27:59 rousskov Exp $
  *
  * DEBUG: section 58    HTTP Reply (Response)
  * AUTHOR: Alex Rousskov
@@ -40,6 +40,7 @@
 #include "HttpHdrContRange.h"
 #include "HttpHdrSc.h"
 #include "ACLChecklist.h"
+#include "HttpRequest.h"
 #include "MemBuf.h"
 
 /* local constants */
@@ -77,7 +78,9 @@ httpReplyInitModule(void)
     httpHeaderCalcMask(&Denied304HeadersMask, Denied304HeadersArr, countof(Denied304HeadersArr));
 }
 
-HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0), protoPrefix("HTTP/")
+HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), 
+       expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0), 
+       protoPrefix("HTTP/"), bodySizeMax(-2)
 {
     init();
 }
@@ -122,6 +125,7 @@ HttpReply::clean()
     hdrCacheClean();
     header.clean();
     httpStatusLineClean(&sline);
+    bodySizeMax = -2; // hack: make calculatedBodySizeMax() false
 }
 
 void
@@ -496,3 +500,54 @@ HttpReply::expectingBody(const HttpRequestMethod& req_method, int64_t& theSize)
 
     return expectBody;
 }
+
+bool
+HttpReply::receivedBodyTooLarge(HttpRequest& request, int64_t receivedSize)
+{
+    calcMaxBodySize(request);
+    debugs(58, 3, HERE << receivedSize << " >? " << bodySizeMax);
+    return bodySizeMax >= 0 && receivedSize > bodySizeMax;
+}
+
+bool
+HttpReply::expectedBodyTooLarge(HttpRequest& request)
+{
+    calcMaxBodySize(request);
+    debugs(58, 7, HERE << "bodySizeMax=" << bodySizeMax);
+
+    if (bodySizeMax < 0) // no body size limit
+        return false;
+
+    int64_t expectedSize = -1;
+    if (!expectingBody(request.method, expectedSize))
+        return false;
+    
+    debugs(58, 6, HERE << expectedSize << " >? " << bodySizeMax);
+
+    if (expectedSize < 0) // expecting body of an unknown length
+        return false;
+
+    return expectedSize > bodySizeMax;
+}
+
+void
+HttpReply::calcMaxBodySize(HttpRequest& request)
+{
+    // hack: -2 is used as "we have not calculated max body size yet" state
+    if (bodySizeMax != -2) // already tried
+        return;
+    bodySizeMax = -1;
+
+    ACLChecklist ch;
+    ch.src_addr = request.client_addr;
+    ch.my_addr = request.my_addr;
+    ch.reply = HTTPMSGLOCK(this); // XXX: this lock makes method non-const
+    ch.request = HTTPMSGLOCK(&request);
+    for (acl_size_t *l = Config.ReplyBodySize; l; l = l -> next) {
+        if (ch.matchAclListFast(l->aclList)) {
+            debugs(58, 4, HERE << "bodySizeMax=" << bodySizeMax);
+            bodySizeMax = l->size; // may be -1
+            break;
+        }
+    }
+}
index 6230d05d019d93c79009a7dddea743526f4a39a7..8afd07d31623b2373ca1eb8ee9d2f5cff1d26244 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpReply.h,v 1.22 2008/01/20 08:54:28 amosjeffries Exp $
+ * $Id: HttpReply.h,v 1.23 2008/02/08 18:27:59 rousskov Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -118,6 +118,14 @@ public:
 
     int64_t bodySize(const HttpRequestMethod&) const;
 
+    /// Checks whether received body exceeds known maximum size.
+    /// Requires a prior call to calcMaxBodySize().
+    bool receivedBodyTooLarge(HttpRequest&, int64_t receivedBodySize);
+
+    /// Checks whether expected body exceeds known maximum size.
+    /// Requires a prior call to calcMaxBodySize().
+    bool expectedBodyTooLarge(HttpRequest& request);
+
     int validatorsMatch (HttpReply const *other) const;
 
     void packHeadersInto(Packer * p) const;
@@ -139,6 +147,12 @@ private:
     /* header manipulation */
     time_t hdrExpirationTime();
 
+    // Calculates and stores maximum body size if needed. Used by
+    // receivedBodyTooLarge() and expectedBodyTooLarge().
+    void calcMaxBodySize(HttpRequest& request);
+
+    mutable int64_t bodySizeMax; // cached result of calcMaxBodySize
+
 protected:
     virtual void packFirstLineInto(Packer * p, bool) const;
 
index cf9b3656fb14eb68a8fb1409d8878374783001c3..83bdb0e65924667b777a49b27fdbd2304de93dee 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.cc,v 1.102 2008/02/03 10:00:30 amosjeffries Exp $
+ * $Id: client_side_request.cc,v 1.103 2008/02/08 18:27:59 rousskov Exp $
  * 
  * DEBUG: section 85    Client-side Request Routines
  * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
@@ -926,30 +926,6 @@ ClientHttpRequest::gotEnough() const
     return true;
 }
 
-void
-ClientHttpRequest::maxReplyBodySize(int64_t clen)
-{
-    maxReplyBodySize_ = clen;
-}
-
-int64_t
-ClientHttpRequest::maxReplyBodySize() const
-{
-    return maxReplyBodySize_;
-}
-
-bool
-ClientHttpRequest::isReplyBodyTooLarge(int64_t clen) const
-{
-    if (0 == maxReplyBodySize())
-        return 0;      /* disabled */
-
-    if (clen < 0)
-        return 0;      /* unknown */
-
-    return clen > maxReplyBodySize();
-}
-
 void
 ClientHttpRequest::storeEntry(StoreEntry *newEntry)
 {
index 5234b0a7d04e366bfdbc679e296b1ecebc3fdb0a..17eb4bf68b7e6a67aae931fdacfdcaad39197460 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.h,v 1.34 2008/01/20 08:54:28 amosjeffries Exp $
+ * $Id: client_side_request.h,v 1.35 2008/02/08 18:27:59 rousskov Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -144,10 +144,6 @@ unsigned int purging:
     dlink_list client_stream;
     int mRangeCLen();
 
-    int64_t maxReplyBodySize() const;
-    void maxReplyBodySize(int64_t size);
-    bool isReplyBodyTooLarge(int64_t len) const;
-
     ClientRequestContext *calloutContext;
     void doCallouts();