From 16995ad8c83b48dc64a2b20fb7cd7a421245b1ab Mon Sep 17 00:00:00 2001 From: gregw Date: Sun, 19 May 2024 09:22:49 +1000 Subject: [PATCH 1/3] Fixed header cache for unknown values Avoid adding the unknown marker into the CACHE index. Issue introduced in #11661 fixing #11659 --- .../org/eclipse/jetty/http/HttpParser.java | 8 +++++++- .../org/eclipse/jetty/http/HttpParserTest.java | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 810c8f11c7c8..b4193ffb4383 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -146,17 +146,22 @@ public class HttpParser { HttpField field = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type); map.put(field.toString(), field); + map.put(field.toString().replace(": ", ":"), field); for (String charset : new String[]{"utf-8", "iso-8859-1"}) { PreEncodedHttpField field1 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + ";charset=" + charset); map.put(field1.toString(), field1); + map.put(field1.toString().replace(": ", ":"), field1); PreEncodedHttpField field2 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + "; charset=" + charset); map.put(field2.toString(), field2); + map.put(field1.toString().replace(": ", ":"), field2); PreEncodedHttpField field3 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + ";charset=" + charset.toUpperCase(Locale.ENGLISH)); map.put(field3.toString(), field3); + map.put(field1.toString().replace(": ", ":"), field3); PreEncodedHttpField field4 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + "; charset=" + charset.toUpperCase(Locale.ENGLISH)); map.put(field4.toString(), field4); + map.put(field1.toString().replace(": ", ":"), field4); } } return map; @@ -167,7 +172,8 @@ public class HttpParser for (HttpHeader h : HttpHeader.values()) { HttpField httpField = new HttpField(h, UNMATCHED_VALUE); - map.put(httpField.toString(), httpField); + map.put(h + ": ", httpField); + map.put(h + ":", httpField); } return map; }) diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index 57db19b52898..d58598132640 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -358,6 +358,24 @@ public void testLowerCaseVersion(String eoln) assertEquals(1, _headers); } + @Test + public void testHeaderCache() + { + assertThat(HttpParser.CACHE.getBest("Content-Type: text/plain\r\n").toString(), is("Content-Type: text/plain")); + assertThat(HttpParser.CACHE.getBest("Content-Type: text/plain\n").toString(), is("Content-Type: text/plain")); + assertThat(HttpParser.CACHE.getBest("content-type: text/plain\r\n").toString(), is("Content-Type: text/plain")); + assertThat(HttpParser.CACHE.getBest("content-type: text/plain\n").toString(), is("Content-Type: text/plain")); + assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\r\n").toString(), is("Content-Type: text/plain")); + assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\n").toString(), is("Content-Type: text/plain")); + + assertThat(HttpParser.CACHE.getBest("Content-Type: unknown\r\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("Content-Type: unknown\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("content-type: unknown\r\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("content-type: unknown\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("content-type:unknown\r\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("content-type:unknown\n").toString(), is("Content-Type: \u0000")); + } + @ParameterizedTest @ValueSource(strings = {"\r\n", "\n"}) public void testHeaderCacheNearMiss(String eoln) From d79a0a8a94ac66c57dee73ebd7f9520a5e0d726f Mon Sep 17 00:00:00 2001 From: gregw Date: Sun, 19 May 2024 09:43:55 +1000 Subject: [PATCH 2/3] Fixed header cache for unknown values Avoid adding the unknown marker into the CACHE index. Issue introduced in #11661 fixing #11659 --- .../src/main/java/org/eclipse/jetty/http/HttpParser.java | 5 ----- .../src/test/java/org/eclipse/jetty/http/HttpParserTest.java | 5 +++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index b4193ffb4383..e17830feba9b 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -146,22 +146,17 @@ public class HttpParser { HttpField field = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type); map.put(field.toString(), field); - map.put(field.toString().replace(": ", ":"), field); for (String charset : new String[]{"utf-8", "iso-8859-1"}) { PreEncodedHttpField field1 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + ";charset=" + charset); map.put(field1.toString(), field1); - map.put(field1.toString().replace(": ", ":"), field1); PreEncodedHttpField field2 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + "; charset=" + charset); map.put(field2.toString(), field2); - map.put(field1.toString().replace(": ", ":"), field2); PreEncodedHttpField field3 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + ";charset=" + charset.toUpperCase(Locale.ENGLISH)); map.put(field3.toString(), field3); - map.put(field1.toString().replace(": ", ":"), field3); PreEncodedHttpField field4 = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, type + "; charset=" + charset.toUpperCase(Locale.ENGLISH)); map.put(field4.toString(), field4); - map.put(field1.toString().replace(": ", ":"), field4); } } return map; diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index d58598132640..71e82fb59218 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -365,13 +365,14 @@ public void testHeaderCache() assertThat(HttpParser.CACHE.getBest("Content-Type: text/plain\n").toString(), is("Content-Type: text/plain")); assertThat(HttpParser.CACHE.getBest("content-type: text/plain\r\n").toString(), is("Content-Type: text/plain")); assertThat(HttpParser.CACHE.getBest("content-type: text/plain\n").toString(), is("Content-Type: text/plain")); - assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\r\n").toString(), is("Content-Type: text/plain")); - assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\n").toString(), is("Content-Type: text/plain")); assertThat(HttpParser.CACHE.getBest("Content-Type: unknown\r\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("Content-Type: unknown\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type: unknown\r\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type: unknown\n").toString(), is("Content-Type: \u0000")); + + assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\r\n").toString(), is("Content-Type: \u0000")); + assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type:unknown\r\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type:unknown\n").toString(), is("Content-Type: \u0000")); } From 69ad90f7b9950d571dd5f0879aa806ea2fc49102 Mon Sep 17 00:00:00 2001 From: gregw Date: Mon, 20 May 2024 07:31:36 +1000 Subject: [PATCH 3/3] Fixed header cache for unknown values Avoid adding the unknown marker into the CACHE index. Issue introduced in #11661 fixing #11659 --- .../src/main/java/org/eclipse/jetty/http/HttpParser.java | 1 - .../src/test/java/org/eclipse/jetty/http/HttpParserTest.java | 5 ----- 2 files changed, 6 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index e17830feba9b..ef1ba9f61da5 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -168,7 +168,6 @@ public class HttpParser { HttpField httpField = new HttpField(h, UNMATCHED_VALUE); map.put(h + ": ", httpField); - map.put(h + ":", httpField); } return map; }) diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index 71e82fb59218..603c314d7684 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -370,11 +370,6 @@ public void testHeaderCache() assertThat(HttpParser.CACHE.getBest("Content-Type: unknown\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type: unknown\r\n").toString(), is("Content-Type: \u0000")); assertThat(HttpParser.CACHE.getBest("content-type: unknown\n").toString(), is("Content-Type: \u0000")); - - assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\r\n").toString(), is("Content-Type: \u0000")); - assertThat(HttpParser.CACHE.getBest("Content-Type:text/plain\n").toString(), is("Content-Type: \u0000")); - assertThat(HttpParser.CACHE.getBest("content-type:unknown\r\n").toString(), is("Content-Type: \u0000")); - assertThat(HttpParser.CACHE.getBest("content-type:unknown\n").toString(), is("Content-Type: \u0000")); } @ParameterizedTest