Skip to content

Commit 127a64d

Browse files
yhiroseGavin1937
andauthored
Skip preamble and epilogue in multipart/form-data (Fix #1317) (#1320)
* fix: skip MIME preamble (#1317) * Skip epilogue in multipart/form-data Co-authored-by: Gavin1937 <[email protected]>
1 parent caa31aa commit 127a64d

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

httplib.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,7 @@ class MultipartFormDataParser {
37943794
switch (state_) {
37953795
case 0: { // Initial boundary
37963796
auto pattern = dash_ + boundary_ + crlf_;
3797+
buf_erase(buf_find(pattern));
37973798
if (pattern.size() > buf_size()) { return true; }
37983799
if (!buf_start_with(pattern)) { return false; }
37993800
buf_erase(pattern.size());
@@ -3887,17 +3888,13 @@ class MultipartFormDataParser {
38873888
if (buf_start_with(pattern)) {
38883889
buf_erase(pattern.size());
38893890
is_valid_ = true;
3890-
state_ = 5;
3891+
buf_erase(buf_size()); // Remove epilogue
38913892
} else {
38923893
return true;
38933894
}
38943895
}
38953896
break;
38963897
}
3897-
case 5: { // Done
3898-
is_valid_ = false;
3899-
return false;
3900-
}
39013898
}
39023899
}
39033900

test/test.cc

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,8 +3015,10 @@ TEST(GzipDecompressor, ChunkedDecompression) {
30153015
httplib::detail::gzip_compressor compressor;
30163016
bool result = compressor.compress(
30173017
data.data(), data.size(),
3018-
/*last=*/true, [&](const char *compressed_data_chunk, size_t compressed_data_size) {
3019-
compressed_data.insert(compressed_data.size(), compressed_data_chunk, compressed_data_size);
3018+
/*last=*/true,
3019+
[&](const char *compressed_data_chunk, size_t compressed_data_size) {
3020+
compressed_data.insert(compressed_data.size(), compressed_data_chunk,
3021+
compressed_data_size);
30203022
return true;
30213023
});
30223024
ASSERT_TRUE(result);
@@ -3035,8 +3037,11 @@ TEST(GzipDecompressor, ChunkedDecompression) {
30353037
std::min(compressed_data.size() - chunk_begin, chunk_size);
30363038
bool result = decompressor.decompress(
30373039
compressed_data.data() + chunk_begin, current_chunk_size,
3038-
[&](const char *decompressed_data_chunk, size_t decompressed_data_chunk_size) {
3039-
decompressed_data.insert(decompressed_data.size(), decompressed_data_chunk, decompressed_data_chunk_size);
3040+
[&](const char *decompressed_data_chunk,
3041+
size_t decompressed_data_chunk_size) {
3042+
decompressed_data.insert(decompressed_data.size(),
3043+
decompressed_data_chunk,
3044+
decompressed_data_chunk_size);
30403045
return true;
30413046
});
30423047
ASSERT_TRUE(result);
@@ -4974,5 +4979,48 @@ TEST(MultipartFormDataTest, LargeData) {
49744979
svr.stop();
49754980
t.join();
49764981
}
4982+
4983+
TEST(MultipartFormDataTest, WithPreamble) {
4984+
Server svr;
4985+
svr.Post("/post", [&](const Request &req, Response &res) {
4986+
res.set_content("ok", "text/plain");
4987+
});
4988+
4989+
thread t = thread([&] { svr.listen(HOST, PORT); });
4990+
while (!svr.is_running()) {
4991+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
4992+
}
4993+
4994+
const std::string body =
4995+
"This is the preamble. It is to be ignored, though it\r\n"
4996+
"is a handy place for composition agents to include an\r\n"
4997+
"explanatory note to non-MIME conformant readers.\r\n"
4998+
"\r\n"
4999+
"\r\n"
5000+
"--simple boundary\r\n"
5001+
"Content-Disposition: form-data; name=\"field1\"\r\n"
5002+
"\r\n"
5003+
"value1\r\n"
5004+
"--simple boundary\r\n"
5005+
"Content-Disposition: form-data; name=\"field2\"; "
5006+
"filename=\"example.txt\"\r\n"
5007+
"\r\n"
5008+
"value2\r\n"
5009+
"--simple boundary--\r\n"
5010+
"This is the epilogue. It is also to be ignored.\r\n";
5011+
5012+
std::string content_type =
5013+
R"(multipart/form-data; boundary="simple boundary")";
5014+
5015+
Client cli(HOST, PORT);
5016+
auto res = cli.Post("/post", body, content_type.c_str());
5017+
5018+
ASSERT_TRUE(res);
5019+
EXPECT_EQ(200, res->status);
5020+
5021+
svr.stop();
5022+
t.join();
5023+
}
5024+
49775025
#endif
49785026

0 commit comments

Comments
 (0)