mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-17 10:59:39 +00:00
Escape quote, CR and LF in multipart field names and filenames
detail::serialize_multipart_formdata_item_begin() concatenated item.name
and item.filename into the Content-Disposition quoted-string without any
escaping. A '"' in either value silently terminated the quoted-string
early, and embedded CR/LF allowed injecting arbitrary part headers or
forging part boundaries when a filename comes from external input.
Escape both values following the WHATWG HTML standard ('"' -> %22,
CR -> %0D, LF -> %0A), which matches what browsers send in
multipart/form-data bodies. Behavior only changes for inputs that
previously produced malformed HTTP.
This commit is contained in:
1 parent
3fe32b63b4
commit
8149bb38fc
2 files changed
+80
-2
No files matched your search
@@ -8318,14 +8318,32 @@ inline bool is_multipart_boundary_chars_valid(const std::string &boundary) {
|
||||
return valid;
|
||||
}
|
||||
|
||||
// Escape a multipart field name/filename following the WHATWG HTML standard
|
||||
// ("escape a multipart form-data name"), which is what browsers send:
|
||||
// '"' -> %22, CR -> %0D, LF -> %0A
|
||||
inline std::string escape_multipart_field(const std::string &s) {
|
||||
std::string result;
|
||||
result.reserve(s.size());
|
||||
for (auto c : s) {
|
||||
switch (c) {
|
||||
case '"': result += "%22"; break;
|
||||
case '\r': result += "%0D"; break;
|
||||
case '\n': result += "%0A"; break;
|
||||
default: result += c; break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string
|
||||
serialize_multipart_formdata_item_begin(const T &item,
|
||||
const std::string &boundary) {
|
||||
std::string body = "--" + boundary + "\r\n";
|
||||
body += "Content-Disposition: form-data; name=\"" + item.name + "\"";
|
||||
body += "Content-Disposition: form-data; name=\"" +
|
||||
escape_multipart_field(item.name) + "\"";
|
||||
if (!item.filename.empty()) {
|
||||
body += "; filename=\"" + item.filename + "\"";
|
||||
body += "; filename=\"" + escape_multipart_field(item.filename) + "\"";
|
||||
}
|
||||
body += "\r\n";
|
||||
if (!item.content_type.empty()) {
|
||||
|
||||
Reference in new issue
Block a user