Crow stores client-controlled request-field names in maps using fixed-seed crow::ci_hash or default string hashing. Inputs that collide under the target build may increase map-operation costs. The relevant paths have different limits and activation requirements.
Affected code
Paths below are relative to include/crow/.
- Multipart part names:
multipart_view.h:118,126 defines message_view::part_map. Constructing message_view(req) parses the body (185-189) and inserts each part's Content-Disposition name value as the key (232-234). This requires application use of the multipart parser; examples/example_file_upload.cpp:9 shows that integration.
- Request header names:
http_request.h:52 declares request::headers; parser.h:49,80 inserts parsed wire names. This runs during normal HTTP header parsing.
- Multipart section-header names:
multipart_view.h:43 defines mph_view_map; parse_section_head creates result at 256, extracts names at 276-279, and inserts them at 298. This shares the multipart activation requirement above.
- Cookie names:
middlewares/cookie_parser.h:204 declares the context's jar; before_handle trims and inserts cookie names at 254-255,285. The application must enable CookieParser middleware. Multiple Cookie headers are rejected at 234-241; one header can contain multiple cookie entries.
- Query dictionary subkeys:
query_string::get_dict creates a default-hashed map at query_string.h:481-489. For example, get_dict("filter") extracts client-controlled subkeys from filter[color]=blue. This map is built only when the application calls get_dict or pop_dict (497-500).
The first three stores are unordered_multimap containers using ci_hash and ci_key_eq: hashing starts at zero and mixes uppercased characters (ci_map.h:12-40). They preserve duplicate entries, including case-equivalent names. Cookie and query-dictionary results are unique-key maps using default string hashing. A probe must preserve these container and equality differences.
Relevant insertion statements:
// Multipart part name -> part.
part_map.emplace(
get_header_object(parsed_section.headers, "Content-Disposition")
.params.find("name")->second, parsed_section);
// HTTP and multipart section headers.
self->req.headers.emplace(std::move(self->header_field),
std::move(self->header_value));
result.emplace(key, to_add);
// Cookie name and query dictionary subkey.
ctx.jar.emplace(std::string(name_sv), std::string(value_sv));
ret.insert(*element);
Input limits and impact
- HTTP request line and headers: the parser enforces a default combined 80 KiB limit (
http_parser_merged.h:50-52,292-299,753-754). This constrains URL queries and Cookie input. It does not cap multipart section headers, which are inside the body.
- Query dictionary:
MAX_KEY_VALUE_PAIRS_COUNT = 256 (query_string.h:333) limits the pairs retained during construction (376-379; qs_parse loop at 125-133). The dictionary cannot grow beyond those retained pairs. Its helper also rescans the parameter list for successive entries (215-225,488), so dictionary-building time must distinguish scanning cost from hash-collision cost.
- Multipart: no explicit part-count or section-header-count cap appears in the cited loops.
parser.h:88-92 appends body data without a body-size check in that callback; deployment-level body limits and checks before constructing message_view remain relevant.
These are request/message-scoped entries, not persistent session-table populations. Practical impact depends on accepted input, the selected container implementation, and its collision and rehash behavior.
Suggested fix
Use a keyed hash designed to resist hash flooding, preserving the existing case-insensitive header behavior. Keep the HTTP header and query-count limits; add practical body, multipart part/section-header, and cookie-count limits where appropriate.
Crow stores client-controlled request-field names in maps using fixed-seed
crow::ci_hashor default string hashing. Inputs that collide under the target build may increase map-operation costs. The relevant paths have different limits and activation requirements.Affected code
Paths below are relative to
include/crow/.multipart_view.h:118,126definesmessage_view::part_map. Constructingmessage_view(req)parses the body (185-189) and inserts each part'sContent-Dispositionnamevalue as the key (232-234). This requires application use of the multipart parser;examples/example_file_upload.cpp:9shows that integration.http_request.h:52declaresrequest::headers;parser.h:49,80inserts parsed wire names. This runs during normal HTTP header parsing.multipart_view.h:43definesmph_view_map;parse_section_headcreatesresultat256, extracts names at276-279, and inserts them at298. This shares the multipart activation requirement above.middlewares/cookie_parser.h:204declares the context'sjar;before_handletrims and inserts cookie names at254-255,285. The application must enableCookieParsermiddleware. Multiple Cookie headers are rejected at234-241; one header can contain multiple cookie entries.query_string::get_dictcreates a default-hashed map atquery_string.h:481-489. For example,get_dict("filter")extracts client-controlled subkeys fromfilter[color]=blue. This map is built only when the application callsget_dictorpop_dict(497-500).The first three stores are
unordered_multimapcontainers usingci_hashandci_key_eq: hashing starts at zero and mixes uppercased characters (ci_map.h:12-40). They preserve duplicate entries, including case-equivalent names. Cookie and query-dictionary results are unique-key maps using default string hashing. A probe must preserve these container and equality differences.Relevant insertion statements:
Input limits and impact
http_parser_merged.h:50-52,292-299,753-754). This constrains URL queries and Cookie input. It does not cap multipart section headers, which are inside the body.MAX_KEY_VALUE_PAIRS_COUNT = 256(query_string.h:333) limits the pairs retained during construction (376-379;qs_parseloop at125-133). The dictionary cannot grow beyond those retained pairs. Its helper also rescans the parameter list for successive entries (215-225,488), so dictionary-building time must distinguish scanning cost from hash-collision cost.parser.h:88-92appends body data without a body-size check in that callback; deployment-level body limits and checks before constructingmessage_viewremain relevant.These are request/message-scoped entries, not persistent session-table populations. Practical impact depends on accepted input, the selected container implementation, and its collision and rehash behavior.
Suggested fix
Use a keyed hash designed to resist hash flooding, preserving the existing case-insensitive header behavior. Keep the HTTP header and query-count limits; add practical body, multipart part/section-header, and cookie-count limits where appropriate.