Ignore quoted-strings when parsing an Accept header

parse_accept_header() split on every ',' and then on every ';', with no
idea that a parameter value can be a quoted-string (RFC 9110 §5.6.6). A
value such as text/html;profile="a,b" was cut in the middle, and the
request was answered with 400.

The parser never looks at a parameter value, so remove each
quoted-string (§5.6.4) before parsing rather than teach every split
about quotes. A header without a '"' takes the same path as before.

A quoted-string is removed wherever it appears, so a malformed value
can now be read without it instead of being rejected, and an
unterminated quote hides the rest of the value.
This commit is contained in:
yhirose committed 2026-10-12 22:59:47 -04:00
1 parent 33d84a12b6
commit cbaf751da1
2 files changed
+55

No files matched your search

+22
View File
@@ -9247,8 +9247,30 @@ inline bool parse_range_header(const std::string &s, Ranges &ranges) try {
} catch (...) { return false; }
#endif
// Removes each quoted-string, honoring a quoted-pair (RFC 9110 Section 5.6.4)
inline std::string remove_quoted_strings(const std::string &s) {
std::string out;
auto in_quotes = false;
for (size_t i = 0; i < s.size(); i++) {
if (s[i] == '"') {
in_quotes = !in_quotes;
} else if (!in_quotes) {
out += s[i];
} else if (s[i] == '\\') {
i++;
}
}
return out;
}
inline bool parse_accept_header(const std::string &s,
std::vector<std::string> &content_types) {
// Parameter values are not used here, so a quoted-string is dropped rather
// than parsed: a ',' or ';' inside one must not be read as a delimiter.
if (s.find('"') != std::string::npos) {
return parse_accept_header(remove_quoted_strings(s), content_types);
}
content_types.clear();
// Empty string is considered valid (no preference)