Skip to content

Commit

Permalink
Better compliance to RFC7230/RFC3875 when building CGI headers
Browse files Browse the repository at this point in the history
  • Loading branch information
lpereira committed Apr 29, 2024
1 parent 2718dc2 commit ce4161c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 64 deletions.
1 change: 1 addition & 0 deletions src/lib/lwan-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ uint8_t lwan_char_isxdigit(char ch) __attribute__((pure));
uint8_t lwan_char_isdigit(char ch) __attribute__((pure));
uint8_t lwan_char_isalpha(char ch) __attribute__((pure));
uint8_t lwan_char_isalnum(char ch) __attribute__((pure));
uint8_t lwan_char_iscgiheader(char ch) __attribute__((pure));

static ALWAYS_INLINE __attribute__((pure)) size_t lwan_nextpow2(size_t number)
{
Expand Down
3 changes: 1 addition & 2 deletions src/lib/lwan-request.c
Original file line number Diff line number Diff line change
Expand Up @@ -2254,11 +2254,10 @@ void lwan_request_foreach_header_for_cgi(struct lwan_request *request,
if (r < 0 || r >= (int)sizeof(header_name))
continue;

/* FIXME: RFC7230/RFC3875 compliance */
for (char *p = header_name; *p; p++) {
if (lwan_char_isalpha(*p))
*p &= ~0x20;
else if (!lwan_char_isdigit(*p))
else if (!lwan_char_iscgiheader(*p))
*p = '_';
}

Expand Down
144 changes: 82 additions & 62 deletions src/lib/lwan-tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,82 +196,102 @@ enum {
CHAR_PROP_HEX = 1 << 1,
CHAR_PROP_DIG = 1 << 2,
CHAR_PROP_ALPHA = 1 << 3,
CHAR_PROP_CGI_HEADER = 1 << 4,
};

static const uint8_t char_prop_tbl[256] = {
[' '] = CHAR_PROP_SPACE,
['\t'] = CHAR_PROP_SPACE,
['\n'] = CHAR_PROP_SPACE,
['\r'] = CHAR_PROP_SPACE,
['0'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['1'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['2'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['3'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['4'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['5'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['6'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['7'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['8'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['9'] = CHAR_PROP_HEX | CHAR_PROP_DIG,
['a'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['b'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['c'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['d'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['e'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['f'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['g'] = CHAR_PROP_ALPHA,
['h'] = CHAR_PROP_ALPHA,
['i'] = CHAR_PROP_ALPHA,
['j'] = CHAR_PROP_ALPHA,
['k'] = CHAR_PROP_ALPHA,
['l'] = CHAR_PROP_ALPHA,
['m'] = CHAR_PROP_ALPHA,
['n'] = CHAR_PROP_ALPHA,
['o'] = CHAR_PROP_ALPHA,
['p'] = CHAR_PROP_ALPHA,
['q'] = CHAR_PROP_ALPHA,
['r'] = CHAR_PROP_ALPHA,
['s'] = CHAR_PROP_ALPHA,
['t'] = CHAR_PROP_ALPHA,
['u'] = CHAR_PROP_ALPHA,
['v'] = CHAR_PROP_ALPHA,
['w'] = CHAR_PROP_ALPHA,
['x'] = CHAR_PROP_ALPHA,
['y'] = CHAR_PROP_ALPHA,
['z'] = CHAR_PROP_ALPHA,
['A'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['B'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['C'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['D'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['E'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['F'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA,
['G'] = CHAR_PROP_ALPHA,
['H'] = CHAR_PROP_ALPHA,
['I'] = CHAR_PROP_ALPHA,
['J'] = CHAR_PROP_ALPHA,
['K'] = CHAR_PROP_ALPHA,
['L'] = CHAR_PROP_ALPHA,
['M'] = CHAR_PROP_ALPHA,
['N'] = CHAR_PROP_ALPHA,
['O'] = CHAR_PROP_ALPHA,
['P'] = CHAR_PROP_ALPHA,
['Q'] = CHAR_PROP_ALPHA,
['R'] = CHAR_PROP_ALPHA,
['S'] = CHAR_PROP_ALPHA,
['T'] = CHAR_PROP_ALPHA,
['U'] = CHAR_PROP_ALPHA,
['V'] = CHAR_PROP_ALPHA,
['W'] = CHAR_PROP_ALPHA,
['X'] = CHAR_PROP_ALPHA,
['Y'] = CHAR_PROP_ALPHA,
['Z'] = CHAR_PROP_ALPHA,
['0'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['1'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['2'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['3'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['4'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['5'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['6'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['7'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['8'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['9'] = CHAR_PROP_HEX | CHAR_PROP_DIG | CHAR_PROP_CGI_HEADER,
['a'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['b'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['c'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['d'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['e'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['f'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['g'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['h'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['i'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['j'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['k'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['l'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['m'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['n'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['o'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['p'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['q'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['r'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['s'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['t'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['u'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['v'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['w'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['x'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['y'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['z'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['A'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['B'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['C'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['D'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['E'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['F'] = CHAR_PROP_HEX | CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['G'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['H'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['I'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['J'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['K'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['L'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['M'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['N'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['O'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['P'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['Q'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['R'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['S'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['T'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['U'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['V'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['W'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['X'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['Y'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['Z'] = CHAR_PROP_ALPHA | CHAR_PROP_CGI_HEADER,
['!'] = CHAR_PROP_CGI_HEADER,
['#'] = CHAR_PROP_CGI_HEADER,
['$'] = CHAR_PROP_CGI_HEADER,
['%'] = CHAR_PROP_CGI_HEADER,
['&'] = CHAR_PROP_CGI_HEADER,
['\''] = CHAR_PROP_CGI_HEADER,
['*'] = CHAR_PROP_CGI_HEADER,
['+'] = CHAR_PROP_CGI_HEADER,
['.'] = CHAR_PROP_CGI_HEADER,
['^'] = CHAR_PROP_CGI_HEADER,
['_'] = CHAR_PROP_CGI_HEADER,
['`'] = CHAR_PROP_CGI_HEADER,
['|'] = CHAR_PROP_CGI_HEADER,
['~'] = CHAR_PROP_CGI_HEADER,
};

ALWAYS_INLINE uint8_t lwan_char_isspace(char ch)
{
return char_prop_tbl[(unsigned char)ch] & CHAR_PROP_SPACE;
}

ALWAYS_INLINE uint8_t lwan_char_iscgiheader(char ch)
{
return char_prop_tbl[(unsigned char)ch] & CHAR_PROP_CGI_HEADER;
}

ALWAYS_INLINE uint8_t lwan_char_isxdigit(char ch)
{
return char_prop_tbl[(unsigned char)ch] & CHAR_PROP_HEX;
Expand Down

0 comments on commit ce4161c

Please sign in to comment.