[master] e40007dfc Add all well-known headers to the perfect hash lookup table
Martin Blix Grydeland
martin at varnish-software.com
Tue Nov 8 10:02:09 UTC 2022
commit e40007dfc2243fb5b3be9923f1ed22dfebb90002
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Thu Sep 29 14:38:05 2022 +0200
Add all well-known headers to the perfect hash lookup table
This expands the perfect hash lookup table to be able to match any entry
in the list of well-known headers from tbl/http_headers.h.
Previously only the headers that had a non-zero filter flag section was
kept in the fast match table.
Fixes: VSV00010
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 3e78feda6..fe6fcb03d 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -70,73 +70,113 @@ static char * via_hdr;
* A suitable algorithm can be found with `gperf`:
*
* tr '" ,' ' ' < include/tbl/http_headers.h |
- * awk '$1 == "H(" && $4 != "0" {print$2}' |
+ * awk '$1 == "H(" {print $2}' |
* gperf --ignore-case
*
*/
+#define GPERF_MIN_WORD_LENGTH 2
+#define GPERF_MAX_WORD_LENGTH 19
+#define GPERF_MAX_HASH_VALUE 79
+
static const unsigned char http_asso_values[256] = {
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 25, 39, 0, 20, 5, 39, 39, 39, 15, 0, 39,
- 10, 39, 0, 39, 15, 10, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 25, 39, 0, 20, 5, 39, 39, 39, 15, 0, 39,
- 10, 39, 0, 39, 15, 10, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 0, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 5, 80, 20, 0, 0,
+ 5, 10, 5, 5, 80, 0, 15, 0, 20, 80,
+ 40, 80, 0, 35, 10, 20, 55, 45, 0, 0,
+ 80, 80, 80, 80, 80, 80, 80, 5, 80, 20,
+ 0, 0, 5, 10, 5, 5, 80, 0, 15, 0,
+ 20, 80, 40, 80, 0, 35, 10, 20, 55, 45,
+ 0, 0, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80
};
static struct http_hdrflg {
char *hdr;
unsigned flag;
-} http_hdrflg[38 + 1] = { // MAX_HASH_VALUE
- { NULL },
- { NULL },
- { H_TE },
- { H_Age },
- { NULL },
+} http_hdrflg[GPERF_MAX_HASH_VALUE + 1] = {
+ { NULL }, { NULL }, { NULL }, { NULL },
+ { H_Date },
{ H_Range },
{ NULL },
- { H_Upgrade },
+ { H_Referer },
+ { H_Age },
+ { H_From },
+ { H_Keep_Alive },
+ { H_Retry_After },
+ { H_TE },
{ H_If_Range },
- { NULL },
- { H_Connection },
- { NULL },
+ { H_ETag },
+ { H_X_Forwarded_For },
+ { H_Expect },
{ H_Trailer },
- { H_If_None_Match },
- { NULL },
- { NULL },
- { NULL },
- { H_Transfer_Encoding },
- { H_Proxy_Authenticate },
- { H_Proxy_Authorization },
- { H_Keep_Alive },
- { NULL },
- { NULL },
{ H_If_Match },
- { H_HTTP2_Settings },
- { NULL },
- { NULL },
- { NULL },
- { H_Content_Range },
+ { H_Host },
+ { H_Accept_Language },
+ { H_Accept },
+ { H_If_Modified_Since },
+ { H_If_None_Match },
{ H_If_Unmodified_Since },
{ NULL },
+ { H_Cookie },
+ { H_Upgrade },
+ { H_Last_Modified },
+ { H_Accept_Charset },
+ { H_Accept_Encoding },
+ { H_Content_MD5 },
+ { H_Content_Type },
+ { H_Content_Range },
+ { NULL }, { NULL },
+ { H_Content_Language },
+ { H_Transfer_Encoding },
+ { H_Authorization },
+ { H_Content_Length },
+ { H_User_Agent },
+ { H_Server },
+ { H_Expires },
+ { H_Location },
{ NULL },
- { H_If_Modified_Since },
+ { H_Set_Cookie },
+ { H_Content_Encoding },
+ { H_Max_Forwards },
{ H_Cache_Control },
{ NULL },
+ { H_Connection },
+ { H_Pragma },
{ NULL },
+ { H_Accept_Ranges },
+ { H_HTTP2_Settings },
+ { H_Allow },
+ { H_Content_Location },
{ NULL },
+ { H_Proxy_Authenticate },
+ { H_Vary },
{ NULL },
- { H_Accept_Ranges }
+ { H_WWW_Authenticate },
+ { H_Warning },
+ { H_Via },
+ { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL },
+ { H_Proxy_Authorization }
};
static struct http_hdrflg *
@@ -150,11 +190,11 @@ http_hdr_flags(const char *b, const char *e)
assert(b <= e);
u = (unsigned)(e - b);
assert(b + u == e);
- if (u < 2 || u > 19) // MIN_WORD_LENGTH & MAX_WORD_LENGTH
+ if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
return (NULL);
- if (u > 3)
- u += http_asso_values[((const uint8_t*)b)[3]];
- if (u > 38) // MAX_HASH_VALUE
+ u += http_asso_values[((const uint8_t *)b)[u - 1]] +
+ http_asso_values[((const uint8_t *)b)[0]];
+ if (u > GPERF_MAX_HASH_VALUE)
return (NULL);
retval = &http_hdrflg[u];
if (retval->hdr == NULL)
@@ -173,11 +213,9 @@ http_init_hdr(char *hdr, int flg)
hdr[0] = strlen(hdr + 1);
f = http_hdr_flags(hdr + 1, hdr + hdr[0]);
- if (flg) {
- AN(f);
- assert(f->hdr == hdr);
- f->flag = flg;
- }
+ AN(f);
+ assert(f->hdr == hdr);
+ f->flag = flg;
}
void
diff --git a/bin/varnishtest/tests/f00010.vtc b/bin/varnishtest/tests/f00010.vtc
new file mode 100644
index 000000000..b381b5cf3
--- /dev/null
+++ b/bin/varnishtest/tests/f00010.vtc
@@ -0,0 +1,19 @@
+varnishtest "Do not allow critical headers to be marked hop-by-hop"
+
+varnish v1 -vcl {
+ backend default none;
+} -start
+
+client c1 {
+ txreq -hdr "Connection: Content-Length" -body "asdf"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
+
+client c2 {
+ txreq -hdr "Connection: Host"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
More information about the varnish-commit
mailing list