bnc | 30bbde7 | 2022-05-12 06:41:23 -0700 | [diff] [blame] | 1 | #include "quiche/balsa/header_properties.h" |
QUICHE team | d7a507e | 2022-04-15 14:35:46 -0700 | [diff] [blame] | 2 | |
| 3 | #include <array> |
| 4 | |
| 5 | #include "absl/container/flat_hash_set.h" |
| 6 | #include "absl/strings/string_view.h" |
| 7 | #include "quiche/common/quiche_text_utils.h" |
| 8 | |
| 9 | namespace quiche::header_properties { |
| 10 | |
| 11 | namespace { |
| 12 | |
| 13 | using MultivaluedHeadersSet = |
| 14 | absl::flat_hash_set<absl::string_view, StringPieceCaseHash, |
| 15 | StringPieceCaseEqual>; |
| 16 | |
| 17 | MultivaluedHeadersSet* buildMultivaluedHeaders() { |
| 18 | return new MultivaluedHeadersSet({ |
| 19 | "accept", |
| 20 | "accept-charset", |
| 21 | "accept-encoding", |
| 22 | "accept-language", |
| 23 | "accept-ranges", |
| 24 | // The follow four headers are all CORS standard headers |
| 25 | "access-control-allow-headers", |
| 26 | "access-control-allow-methods", |
| 27 | "access-control-expose-headers", |
| 28 | "access-control-request-headers", |
| 29 | "allow", |
| 30 | "cache-control", |
| 31 | // IETF draft makes this have cache-control syntax |
| 32 | "cdn-cache-control", |
| 33 | "connection", |
| 34 | "content-encoding", |
| 35 | "content-language", |
| 36 | "expect", |
| 37 | "if-match", |
| 38 | "if-none-match", |
| 39 | // See RFC 5988 section 5 |
| 40 | "link", |
| 41 | "pragma", |
| 42 | "proxy-authenticate", |
| 43 | "te", |
| 44 | // Used in the opening handshake of the WebSocket protocol. |
| 45 | "sec-websocket-extensions", |
| 46 | // Not mentioned in RFC 2616, but it can have multiple values. |
| 47 | "set-cookie", |
| 48 | "trailer", |
| 49 | "transfer-encoding", |
| 50 | "upgrade", |
| 51 | "vary", |
| 52 | "via", |
| 53 | "warning", |
| 54 | "www-authenticate", |
| 55 | // De facto standard not in the RFCs |
| 56 | "x-forwarded-for", |
| 57 | // Internal Google usage gives this cache-control syntax |
| 58 | "x-go" /**/ "ogle-cache-control", |
| 59 | }); |
| 60 | } |
| 61 | |
bnc | 1e2d7f9 | 2022-05-05 06:45:35 -0700 | [diff] [blame] | 62 | std::array<bool, 256> buildInvalidHeaderKeyCharLookupTable() { |
| 63 | std::array<bool, 256> invalidCharTable; |
| 64 | invalidCharTable.fill(false); |
| 65 | for (uint8_t c : kInvalidHeaderKeyCharList) { |
| 66 | invalidCharTable[c] = true; |
| 67 | } |
| 68 | return invalidCharTable; |
| 69 | } |
| 70 | |
bnc | b6ef201 | 2023-06-28 11:36:18 -0700 | [diff] [blame] | 71 | std::array<bool, 256> buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote() { |
| 72 | std::array<bool, 256> invalidCharTable; |
| 73 | invalidCharTable.fill(false); |
| 74 | for (uint8_t c : kInvalidHeaderKeyCharListAllowDoubleQuote) { |
| 75 | invalidCharTable[c] = true; |
| 76 | } |
| 77 | return invalidCharTable; |
| 78 | } |
| 79 | |
QUICHE team | d7a507e | 2022-04-15 14:35:46 -0700 | [diff] [blame] | 80 | std::array<bool, 256> buildInvalidCharLookupTable() { |
| 81 | std::array<bool, 256> invalidCharTable; |
| 82 | invalidCharTable.fill(false); |
bnc | 049f2e1 | 2022-05-04 13:26:36 -0700 | [diff] [blame] | 83 | for (uint8_t c : kInvalidHeaderCharList) { |
QUICHE team | d7a507e | 2022-04-15 14:35:46 -0700 | [diff] [blame] | 84 | invalidCharTable[c] = true; |
| 85 | } |
| 86 | return invalidCharTable; |
| 87 | } |
| 88 | |
| 89 | } // anonymous namespace |
| 90 | |
| 91 | bool IsMultivaluedHeader(absl::string_view header) { |
| 92 | static const MultivaluedHeadersSet* const multivalued_headers = |
| 93 | buildMultivaluedHeaders(); |
| 94 | return multivalued_headers->contains(header); |
| 95 | } |
| 96 | |
bnc | 1e2d7f9 | 2022-05-05 06:45:35 -0700 | [diff] [blame] | 97 | bool IsInvalidHeaderKeyChar(uint8_t c) { |
| 98 | static const std::array<bool, 256> invalidHeaderKeyCharTable = |
| 99 | buildInvalidHeaderKeyCharLookupTable(); |
| 100 | |
| 101 | return invalidHeaderKeyCharTable[c]; |
| 102 | } |
| 103 | |
bnc | b6ef201 | 2023-06-28 11:36:18 -0700 | [diff] [blame] | 104 | bool IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c) { |
| 105 | static const std::array<bool, 256> invalidHeaderKeyCharTable = |
| 106 | buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote(); |
| 107 | |
| 108 | return invalidHeaderKeyCharTable[c]; |
| 109 | } |
| 110 | |
bnc | 049f2e1 | 2022-05-04 13:26:36 -0700 | [diff] [blame] | 111 | bool IsInvalidHeaderChar(uint8_t c) { |
QUICHE team | d7a507e | 2022-04-15 14:35:46 -0700 | [diff] [blame] | 112 | static const std::array<bool, 256> invalidCharTable = |
| 113 | buildInvalidCharLookupTable(); |
| 114 | |
| 115 | return invalidCharTable[c]; |
| 116 | } |
| 117 | |
| 118 | bool HasInvalidHeaderChars(absl::string_view value) { |
| 119 | for (const char c : value) { |
| 120 | if (IsInvalidHeaderChar(c)) { |
| 121 | return true; |
| 122 | } |
| 123 | } |
| 124 | return false; |
| 125 | } |
| 126 | |
| 127 | } // namespace quiche::header_properties |