in proxygen/lib/http/codec/CodecUtil.h [111:185]
static bool validateHeaderValue(folly::ByteRange value, CtlEscapeMode mode) {
bool escape = false;
bool quote = false;
enum {
lws_none,
lws_expect_nl,
lws_expect_ws1,
lws_expect_ws2
} state = lws_none;
for (auto p = std::begin(value); p != std::end(value); ++p) {
if (escape) {
escape = false;
if (mode == COMPLIANT) {
// prev char escaped. Turn off escape and go to next char
// COMPLIANT mode only
assert(quote);
continue;
}
}
switch (state) {
case lws_none:
switch (*p) {
case '\\':
if (quote) {
escape = true;
}
break;
case '\"':
quote = !quote;
break;
case '\r':
state = lws_expect_nl;
break;
default:
if ((*p < 0x20 && *p != '\t') || (*p == 0x7f) ||
(*p > 0x7f && mode == STRICT)) {
// unexpected ctl per rfc2616, HT OK
return false;
}
break;
}
break;
case lws_expect_nl:
if (*p != '\n') {
// unescaped \r must be LWS
return false;
}
state = lws_expect_ws1;
break;
case lws_expect_ws1:
if (*p != ' ' && *p != '\t') {
// unescaped \r\n must be LWS
return false;
}
state = lws_expect_ws2;
break;
case lws_expect_ws2:
if (*p != ' ' && *p != '\t') {
// terminated LWS
state = lws_none;
// check this char again
p--;
}
break;
}
}
// Unterminated quotes are OK, since the value can be* TEXT which treats
// the " like any other char.
// Unterminated escapes are bad because it will escape the next character
// when converting to HTTP
// Unterminated LWS (dangling \r or \r\n) is bad because it could
// prematurely terminate the headers when converting to HTTP
return !escape && (state == lws_none || state == lws_expect_ws2);
}