mirror of
https://github.com/facebook/proxygen.git
synced 2026-10-24 01:33:54 +03:00
Add plain-ASCII fast path to CodecUtil::validateHeaderValue on HPACK decode path
Reviewed By: yfeldblum Differential Revision: D111136730 fbshipit-source-id: 30da0bc5fea87a52cdfc6e8e77080f135688fecb
This commit is contained in:
committed by
meta-codesync[bot]
parent
d1bad34f59
commit
f5d54ce2dd
@@ -124,6 +124,21 @@ class CodecUtil {
|
||||
|
||||
static HeaderValueError validateHeaderValueDetail(folly::ByteRange value,
|
||||
CtlEscapeMode mode) {
|
||||
// Fast path: values made up entirely of "plain" bytes -- printable
|
||||
// US-ASCII excluding '"' and '\\', plus HTAB -- cannot alter the state
|
||||
// machine below and are valid in every mode. The (c - 0x20) <= 0x5e idiom
|
||||
// folds the 0x20..0x7e range check into a single unsigned compare, keeping
|
||||
// the scan branch-light so the compiler can auto-vectorize it.
|
||||
bool plain = true;
|
||||
for (uint8_t c : value) {
|
||||
plain &=
|
||||
(static_cast<uint8_t>(c - 0x20) <= 0x5e && c != '"' && c != '\\') ||
|
||||
c == '\t';
|
||||
}
|
||||
if (plain) {
|
||||
return HeaderValueError::None;
|
||||
}
|
||||
|
||||
bool escape = false;
|
||||
bool quote = false;
|
||||
enum {
|
||||
|
||||
@@ -186,6 +186,47 @@ TEST(CodecUtil, validateHeaderValueDetail) {
|
||||
Error::DanglingEscape);
|
||||
}
|
||||
|
||||
// Regression guard for the plain-ASCII fast path in validateHeaderValue. The
|
||||
// fast path accepts a value outright only when every byte is "plain" (HTAB or
|
||||
// printable US-ASCII excluding '"' and '\\'); any other byte falls through to
|
||||
// the state machine. These cases pin down the transition bytes on both sides
|
||||
// of that fast/slow split in all three modes, so the fast path can never drift
|
||||
// from the state machine it short-circuits. Expected values are derived from
|
||||
// the RFC rules the state machine implements, not copied from the fast path.
|
||||
TEST(CodecUtil, validateHeaderValueFastPathBoundaries) {
|
||||
auto check = [](const std::string &value,
|
||||
bool compliant,
|
||||
bool strictCompat,
|
||||
bool strict) {
|
||||
auto range = folly::ByteRange{
|
||||
reinterpret_cast<const uint8_t *>(value.data()), value.size()};
|
||||
EXPECT_EQ(CodecUtil::validateHeaderValue(range, CodecUtil::COMPLIANT),
|
||||
compliant);
|
||||
EXPECT_EQ(CodecUtil::validateHeaderValue(range, CodecUtil::STRICT_COMPAT),
|
||||
strictCompat);
|
||||
EXPECT_EQ(CodecUtil::validateHeaderValue(range, CodecUtil::STRICT), strict);
|
||||
};
|
||||
|
||||
// COMPLIANT STRICT_COMPAT STRICT
|
||||
// 0x1F (CTL) rejects; 0x20 (SP) is the first plain byte.
|
||||
check(std::string("a\x1f"), false, false, false);
|
||||
check(std::string("a\x20"), true, true, true);
|
||||
// 0x7E (~) is the last plain byte; 0x7F (DEL) rejects; 0x80 (obs-text) is
|
||||
// accepted except under STRICT.
|
||||
check(std::string("a\x7e"), true, true, true);
|
||||
check(std::string("a\x7f"), false, false, false);
|
||||
check(std::string("a\x80"), true, true, false);
|
||||
// 0x09 (HTAB) is plain; 0x22 (") and 0x5C (\) are the state-machine trigger
|
||||
// bytes (unterminated quote/backslash are accepted).
|
||||
check(std::string("a\x09"), true, true, true);
|
||||
check(std::string("a\""), true, true, true);
|
||||
check(std::string("a\\"), true, true, true);
|
||||
// A quoted-and-escaped CTL is accepted only in COMPLIANT mode.
|
||||
check(std::string("\"\\\x01\""), true, false, false);
|
||||
// An LWS fold (CR LF SP) is accepted in every mode.
|
||||
check(std::string("abc\r\n def"), true, true, true);
|
||||
}
|
||||
|
||||
TEST(CodecUtil, hasGzipAndDeflate) {
|
||||
bool gzip = false;
|
||||
bool deflate = false;
|
||||
|
||||
Reference in New Issue
Block a user