Line data Source code
1 : #pragma once 2 : 3 : #include <array> 4 : #include <cstdint> 5 : 6 : // A set of tables for validating that a character is in a specific 7 : // character set. Used to validate RFC compliance for various HTTP protocol elements. 8 : 9 : namespace Envoy { 10 : namespace Http { 11 : 12 49075 : inline constexpr bool testCharInTable(const std::array<uint32_t, 8>& table, char c) { 13 : // CPU cache friendly version of a lookup in a bit table of size 256. 14 : // The table is organized as 8 32 bit words. 15 : // This function looks up a bit from the `table` at the index `c`. 16 : // This function is used to test whether a character `c` is allowed 17 : // or not based on the value of a bit at index `c`. 18 49075 : uint8_t tmp = static_cast<uint8_t>(c); 19 : // The `tmp >> 5` determines which of the 8 uint32_t words has the bit at index `uc`. 20 : // The `0x80000000 >> (tmp & 0x1f)` determines the index of the bit within the 32 bit word. 21 49075 : return (table[tmp >> 5] & (0x80000000 >> (tmp & 0x1f))) != 0; 22 49075 : } 23 : 24 : // Header name character table. 25 : // From RFC 9110, https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1: 26 : // 27 : // SPELLCHECKER(off) 28 : // header-field = field-name ":" OWS field-value OWS 29 : // field-name = token 30 : // token = 1*tchar 31 : // 32 : // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" 33 : // / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" 34 : // / DIGIT / ALPHA 35 : // SPELLCHECKER(on) 36 : inline constexpr std::array<uint32_t, 8> kGenericHeaderNameCharTable = { 37 : // control characters 38 : 0b00000000000000000000000000000000, 39 : // !"#$%&'()*+,-./0123456789:;<=>? 40 : 0b01011111001101101111111111000000, 41 : //@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ 42 : 0b01111111111111111111111111100011, 43 : //`abcdefghijklmnopqrstuvwxyz{|}~ 44 : 0b11111111111111111111111111101010, 45 : // extended ascii 46 : 0b00000000000000000000000000000000, 47 : 0b00000000000000000000000000000000, 48 : 0b00000000000000000000000000000000, 49 : 0b00000000000000000000000000000000, 50 : }; 51 : 52 : // A URI query and fragment character table. From RFC 3986: 53 : // https://datatracker.ietf.org/doc/html/rfc3986#section-3.4 54 : // 55 : // SPELLCHECKER(off) 56 : // query = *( pchar / "/" / "?" ) 57 : // fragment = *( pchar / "/" / "?" ) 58 : // SPELLCHECKER(on) 59 : inline constexpr std::array<uint32_t, 8> kUriQueryAndFragmentCharTable = { 60 : // control characters 61 : 0b00000000000000000000000000000000, 62 : // !"#$%&'()*+,-./0123456789:;<=>? 63 : 0b01001111111111111111111111110101, 64 : //@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ 65 : 0b11111111111111111111111111100001, 66 : //`abcdefghijklmnopqrstuvwxyz{|}~ 67 : 0b01111111111111111111111111100010, 68 : // extended ascii 69 : 0b00000000000000000000000000000000, 70 : 0b00000000000000000000000000000000, 71 : 0b00000000000000000000000000000000, 72 : 0b00000000000000000000000000000000, 73 : }; 74 : 75 : } // namespace Http 76 : } // namespace Envoy