]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Maintain a "current size of received body" counter. 17284/head
authorMiod Vallat <miod.vallat@powerdns.com>
Mon, 4 May 2026 09:46:09 +0000 (11:46 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Mon, 4 May 2026 09:46:09 +0000 (11:46 +0200)
This allows us to get rid of synthesizing partial body contents as
std::string objects, only to check for their length being still within
allowed bounds.

Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
ext/yahttp/yahttp/reqresp.cpp
ext/yahttp/yahttp/reqresp.hpp

index 7df4b4be8bafccb79ee0c551e6a2c4e92b217ea3..b774c8796104619c4ba730e26283fbe0d4f346f9 100644 (file)
@@ -201,20 +201,25 @@ namespace YaHTTP {
             if (buffer.size() < chunk_size+2 || buffer.at(chunk_size+1) != '\n') return false; // expect newline after carriage return
             crlf=2;
           } else if (buffer.at(chunk_size) != '\n') return false;
-          if (bodybuf.str().length() + chunk_size > maxbody) {
+          if (bodysize + chunk_size > maxbody) {
             throw ParseError("Chunked body is too large");
           }
           std::string tmp = buffer.substr(0, chunk_size);
           buffer.erase(buffer.begin(), buffer.begin()+chunk_size+crlf);
           bodybuf << tmp;
+          bodysize += chunk_size;
           chunk_size = 0;
           if (buffer.size() == 0) break; // just in case
         }
       } else {
-        if (bodybuf.str().length() + buffer.length() > maxbody)
+        if (bodysize + buffer.length() > maxbody) {
           bodybuf << buffer.substr(0, maxbody - bodybuf.str().length());
-        else
+          bodysize = maxbody;
+        }
+        else {
           bodybuf << buffer;
+          bodysize += buffer.length();
+        }
         buffer = "";
       }
     }
index b44bcd91b872f146de7ebd638fdc0717e140902e..bb55a0737c77b97fe83035bff658ca6738be1bcd 100644 (file)
@@ -313,7 +313,8 @@ public:
     std::ostringstream bodybuf; //<! buffer for body
     size_t maxbody; //<! maximum size of body
     size_t minbody; //<! minimum size of body
-    size_t headersize;                 
+    size_t headersize;
+    size_t bodysize;
     bool hasBody; //<! are we expecting body
 
     void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value); //<! key value pair parser helper
@@ -325,28 +326,27 @@ public:
       hasBody = false;
       buffer = "";
       headersize = 0;
+      bodysize = 0;
       this->target->initialize();
     }; //<! Initialize the parser for target and clear state
     bool feed(const std::string& somedata); //<! Feed data to the parser
     bool ready() {
      return (chunked == true && state == 3) || // if it's chunked we get end of data indication
              (chunked == false && state > 1 &&  
-               (!hasBody || 
-                 (bodybuf.str().size() <= maxbody && 
-                  bodybuf.str().size() >= minbody)
-               )
-             ); 
+               (!hasBody || (bodysize <= maxbody && bodysize >= minbody))); 
     }; //<! whether we have received enough data
     void finalize() {
       bodybuf.flush();
       if (ready()) {
+        std::string body = bodybuf.str();
         strstr_map_t::iterator cpos = target->headers.find("content-type");
         if (cpos != target->headers.end() && Utility::iequals(cpos->second, "application/x-www-form-urlencoded", 32)) {
-          target->postvars = Utility::parseUrlParameters(bodybuf.str());
+          target->postvars = Utility::parseUrlParameters(body);
         }
-        target->body = bodybuf.str();
+        target->body = std::move(body);
       }
       bodybuf.str("");
+      bodysize = 0;
       this->target = NULL;
     }; //<! finalize and release target
   };