xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/balsa/header_properties.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 #include "quiche/balsa/header_properties.h"
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 
buildMultivaluedHeaders()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 
buildInvalidHeaderKeyCharLookupTable()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 
buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote()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 
buildInvalidCharLookupTable()80 std::array<bool, 256> buildInvalidCharLookupTable() {
81   std::array<bool, 256> invalidCharTable;
82   invalidCharTable.fill(false);
83   for (uint8_t c : kInvalidHeaderCharList) {
84     invalidCharTable[c] = true;
85   }
86   return invalidCharTable;
87 }
88 
89 }  // anonymous namespace
90 
IsMultivaluedHeader(absl::string_view header)91 bool IsMultivaluedHeader(absl::string_view header) {
92   static const MultivaluedHeadersSet* const multivalued_headers =
93       buildMultivaluedHeaders();
94   return multivalued_headers->contains(header);
95 }
96 
IsInvalidHeaderKeyChar(uint8_t c)97 bool IsInvalidHeaderKeyChar(uint8_t c) {
98   static const std::array<bool, 256> invalidHeaderKeyCharTable =
99       buildInvalidHeaderKeyCharLookupTable();
100 
101   return invalidHeaderKeyCharTable[c];
102 }
103 
IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c)104 bool IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c) {
105   static const std::array<bool, 256> invalidHeaderKeyCharTable =
106       buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote();
107 
108   return invalidHeaderKeyCharTable[c];
109 }
110 
IsInvalidHeaderChar(uint8_t c)111 bool IsInvalidHeaderChar(uint8_t c) {
112   static const std::array<bool, 256> invalidCharTable =
113       buildInvalidCharLookupTable();
114 
115   return invalidCharTable[c];
116 }
117 
HasInvalidHeaderChars(absl::string_view value)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
128