This commit is contained in:
J. Nick Koston 2025-06-29 11:07:25 -05:00
parent 2b7bc1cd9f
commit f57e26c54e
No known key found for this signature in database

View File

@ -9,6 +9,12 @@ namespace web_server_idf {
static const char *const TAG = "multipart_parser"; static const char *const TAG = "multipart_parser";
// Constants for multipart parsing
static constexpr size_t CRLF_LENGTH = 2;
static constexpr size_t MIN_BOUNDARY_BUFFER = 4; // Extra bytes to keep for split boundary detection
static constexpr const char *CRLF_STR = "\r\n";
static constexpr const char *DOUBLE_DASH = "--";
bool MultipartParser::parse(const uint8_t *data, size_t len) { bool MultipartParser::parse(const uint8_t *data, size_t len) {
// Append new data to buffer // Append new data to buffer
if (data && len > 0) { if (data && len > 0) {
@ -105,8 +111,8 @@ bool MultipartParser::find_boundary() {
if (boundary_pos == std::string::npos) { if (boundary_pos == std::string::npos) {
// Keep some data for next iteration to handle split boundaries // Keep some data for next iteration to handle split boundaries
if (buffer_.size() > boundary_.length() + 4) { if (buffer_.size() > boundary_.length() + MIN_BOUNDARY_BUFFER) {
buffer_.erase(buffer_.begin(), buffer_.end() - boundary_.length() - 4); buffer_.erase(buffer_.begin(), buffer_.end() - boundary_.length() - MIN_BOUNDARY_BUFFER);
} }
return false; return false;
} }
@ -115,12 +121,12 @@ bool MultipartParser::find_boundary() {
buffer_.erase(buffer_.begin(), buffer_.begin() + boundary_pos + boundary_.length()); buffer_.erase(buffer_.begin(), buffer_.begin() + boundary_pos + boundary_.length());
// Skip CRLF after boundary // Skip CRLF after boundary
if (buffer_.size() >= 2 && buffer_[0] == '\r' && buffer_[1] == '\n') { if (buffer_.size() >= CRLF_LENGTH && buffer_[0] == '\r' && buffer_[1] == '\n') {
buffer_.erase(buffer_.begin(), buffer_.begin() + 2); buffer_.erase(buffer_.begin(), buffer_.begin() + CRLF_LENGTH);
} }
// Check if this is the end boundary // Check if this is the end boundary
if (buffer_.size() >= 2 && buffer_[0] == '-' && buffer_[1] == '-') { if (buffer_.size() >= CRLF_LENGTH && buffer_[0] == '-' && buffer_[1] == '-') {
state_ = DONE; state_ = DONE;
return false; return false;
} }
@ -133,12 +139,12 @@ bool MultipartParser::parse_headers() {
std::string line = read_line(); std::string line = read_line();
if (line.empty()) { if (line.empty()) {
// Check if we have enough data for a line // Check if we have enough data for a line
auto crlf_pos = find_pattern(reinterpret_cast<const uint8_t *>("\r\n"), 2); auto crlf_pos = find_pattern(reinterpret_cast<const uint8_t *>(CRLF_STR), CRLF_LENGTH);
if (crlf_pos == std::string::npos) { if (crlf_pos == std::string::npos) {
return false; // Need more data return false; // Need more data
} }
// Empty line means headers are done // Empty line means headers are done
buffer_.erase(buffer_.begin(), buffer_.begin() + 2); buffer_.erase(buffer_.begin(), buffer_.begin() + CRLF_LENGTH);
return true; return true;
} }
@ -181,7 +187,7 @@ bool MultipartParser::parse_headers() {
bool MultipartParser::extract_content() { bool MultipartParser::extract_content() {
// Look for next boundary // Look for next boundary
std::string search_boundary = "\r\n" + boundary_; std::string search_boundary = CRLF_STR + boundary_;
size_t boundary_pos = size_t boundary_pos =
find_pattern(reinterpret_cast<const uint8_t *>(search_boundary.c_str()), search_boundary.length()); find_pattern(reinterpret_cast<const uint8_t *>(search_boundary.c_str()), search_boundary.length());
@ -195,8 +201,8 @@ bool MultipartParser::extract_content() {
// No boundary found yet, but we might have partial content // No boundary found yet, but we might have partial content
// Keep enough bytes to ensure we don't split a boundary // Keep enough bytes to ensure we don't split a boundary
size_t safe_length = buffer_.size(); size_t safe_length = buffer_.size();
if (safe_length > search_boundary.length() + 4) { if (safe_length > search_boundary.length() + MIN_BOUNDARY_BUFFER) {
safe_length -= search_boundary.length() + 4; safe_length -= search_boundary.length() + MIN_BOUNDARY_BUFFER;
if (safe_length > 0) { if (safe_length > 0) {
content_length_ = safe_length; content_length_ = safe_length;
// We have partial content but not complete yet // We have partial content but not complete yet
@ -208,13 +214,13 @@ bool MultipartParser::extract_content() {
} }
std::string MultipartParser::read_line() { std::string MultipartParser::read_line() {
auto crlf_pos = find_pattern(reinterpret_cast<const uint8_t *>("\r\n"), 2); auto crlf_pos = find_pattern(reinterpret_cast<const uint8_t *>(CRLF_STR), CRLF_LENGTH);
if (crlf_pos == std::string::npos) { if (crlf_pos == std::string::npos) {
return ""; return "";
} }
std::string line(buffer_.begin(), buffer_.begin() + crlf_pos); std::string line(buffer_.begin(), buffer_.begin() + crlf_pos);
buffer_.erase(buffer_.begin(), buffer_.begin() + crlf_pos + 2); buffer_.erase(buffer_.begin(), buffer_.begin() + crlf_pos + CRLF_LENGTH);
return line; return line;
} }