Procházet zdrojové kódy

Merge pull request #2497 from superm1/superm1/SWSPLAT-23636

Limit the number of header lines per multipart form-data part
yhirose před 2 týdny
rodič
revize
bbd56a7e2c
2 změnil soubory, kde provedl 46 přidání a 0 odebrání
  1. 9 0
      httplib.h
  2. 37 0
      test/test.cc

+ 9 - 0
httplib.h

@@ -8166,6 +8166,13 @@ public:
             break;
           }
 
+          // Check header count limit
+          if (header_count_ >= CPPHTTPLIB_HEADER_MAX_COUNT) {
+            is_valid_ = false;
+            return false;
+          }
+          header_count_++;
+
           const auto header = buf_head(pos);
 
           if (!parse_header(header.data(), header.data() + header.size(),
@@ -8281,6 +8288,7 @@ private:
     file_.filename.clear();
     file_.content_type.clear();
     file_.headers.clear();
+    header_count_ = 0;
   }
 
   bool start_with_case_ignore(const std::string &a, const char *b,
@@ -8334,6 +8342,7 @@ private:
   size_t state_ = 0;
   bool is_valid_ = false;
   FormData file_;
+  size_t header_count_ = 0;
 
   // Buffer
   bool start_with(const std::string &a, size_t spos, size_t epos,

+ 37 - 0
test/test.cc

@@ -13754,6 +13754,43 @@ TEST(MultipartFormDataTest, MakeFileProvider) {
   EXPECT_EQ(StatusCode::OK_200, res->status);
 }
 
+TEST(MultipartFormDataTest, ExcessivePartHeaders) {
+  // Verify that a multipart part with more than CPPHTTPLIB_HEADER_MAX_COUNT
+  // (100) headers is rejected with a 400 Bad Request response.
+  Server svr;
+  svr.Post("/post", [&](const Request & /*req*/, Response &res) {
+    res.set_content("ok", "text/plain");
+  });
+
+  thread t = thread([&] { svr.listen(HOST, PORT); });
+  auto se = detail::scope_exit([&] {
+    svr.stop();
+    t.join();
+    ASSERT_FALSE(svr.is_running());
+  });
+
+  svr.wait_until_ready();
+
+  // Build a multipart part with 101 custom headers (exceeding CPPHTTPLIB_HEADER_MAX_COUNT=100)
+  std::stringstream body;
+  body << "--simpleboundary\r\n"
+       << "Content-Disposition: form-data; name=\"field1\"\r\n";
+  for (int i = 0; i < 101; i++) {
+    body << "X-Custom-Header-" << i << ": value\r\n";
+  }
+  body << "\r\n"
+       << "value1\r\n"
+       << "--simpleboundary--\r\n";
+
+  std::string content_type = "multipart/form-data; boundary=simpleboundary";
+
+  Client cli(HOST, PORT);
+  auto res = cli.Post("/post", body.str(), content_type.c_str());
+
+  ASSERT_TRUE(res);
+  EXPECT_EQ(StatusCode::BadRequest_400, res->status);
+}
+
 TEST(MakeFileBodyTest, Basic) {
   const std::string file_content(4096, 'Z');
   const std::string tmp_path = "./httplib_test_make_file_body.bin";