Skip to content

v0.53.1

Latest

Choose a tag to compare

@yhirose yhirose released this 15 Aug 01:54

What's Changed

Security fixes

  • Reject bytes trailing an IPv6 host literal in parse_url() instead of folding them into the path (#2536, thanks @metsw24-max). http://[::1]evil.com/ previously parsed with host ::1 and path evil.com/, silently dropping the extra bytes rather than rejecting the URL; a ] not followed by :, /, ?, #, or end-of-string is now a parse failure
  • Guard regex routes against stack overflow from long paths. RegexMatcher::match() called std::regex_match() directly on the attacker-controlled request path; for quantified patterns such as (.*), libstdc++'s recursive backtracking implementation recurses roughly once per matched character, so a path of a couple thousand characters (well within the existing 8192-byte request URI limit) reliably crashed the process under the default thread stack size. Add CPPHTTPLIB_REGEX_ROUTE_PATH_MAX_LENGTH (default 256) and reject paths longer than it as a non-match before ever calling std::regex_match()
  • Enforce payload_max_length on the decompressed size for unframed requests. A non-SSL request with neither Content-Length nor Transfer-Encoding read raw wire bytes directly, bypassing the decompressor wrapper the length-framed and chunked paths already use, so payload_max_length only bounded the compressed bytes read off the socket rather than the decompressed size a handler could see. This path is now routed through the same decompressing helper as the others

Performance

  • Match literal route patterns without building a std::regex (#2538). Most registered route patterns are plain literals with no regex metacharacters, but every non-parameter pattern still went through std::regex_match on every request. PathParamsMatcher already does an exact literal comparison when it captures no parameter, so patterns are now routed there whenever they contain none of the 14 ECMAScript metacharacters. Measured with clang -O2 on macOS: scanning routes that all miss until the last one, throughput rises about 24% at 100 routes and roughly 3x at 1000; registering 5000 literal routes drops from about 3.0ms to about 0.9ms. This also confines CPPHTTPLIB_REGEX_ROUTE_PATH_MAX_LENGTH to routes that actually use regex, since literal routes no longer go through RegexMatcher. One visible behavior change: a literal route no longer populates Request::matches (path parameter routes have always behaved this way)

Full Changelog: v0.53.0...v0.53.1