Projects
home:Eustace:branches:Eulaceura:Factory
jetty
_service:obs_scm:CVE-2023-26049.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:CVE-2023-26049.patch of Package jetty
From: Markus Koschany <apo@debian.org> Date: Tue, 26 Sep 2023 23:42:03 +0200 Subject: CVE-2023-26049 Origin: https://github.com/eclipse/jetty.project/pull/9352 --- .../org/eclipse/jetty/http/CookieCompliance.java | 2 +- .../org/eclipse/jetty/server/CookieCutter.java | 205 ++++++++++----- .../org/eclipse/jetty/server/CookieCutterTest.java | 280 ++++++++++++++++----- .../java/org/eclipse/jetty/server/RequestTest.java | 2 + 4 files changed, 361 insertions(+), 128 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java index b2d339c..d514c15 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java @@ -22,4 +22,4 @@ package org.eclipse.jetty.http; * The compliance for Cookie handling. * */ -public enum CookieCompliance { RFC6265, RFC2965 } +public enum CookieCompliance { RFC6265, RFC2965, RFC6265_LEGACY } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java index 5dce1cf..e28d262 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java @@ -107,23 +107,24 @@ public class CookieCutter _lastCookies=null; _fieldList.add(_fields++,f); } - - + protected void parseFields() { - _lastCookies=null; - _cookies=null; - + _lastCookies = null; + _cookies = null; + List<Cookie> cookies = new ArrayList<>(); int version = 0; // delete excess fields - while (_fieldList.size()>_fields) + while (_fieldList.size() > _fields) + { _fieldList.remove(_fields); - - StringBuilder unquoted=null; - + } + + StringBuilder unquoted = null; + // For each cookie field for (String hdr : _fieldList) { @@ -132,25 +133,31 @@ public class CookieCutter Cookie cookie = null; - boolean invalue=false; - boolean inQuoted=false; - boolean quoted=false; - boolean escaped=false; - int tokenstart=-1; - int tokenend=-1; + boolean invalue = false; + boolean inQuoted = false; + boolean quoted = false; + boolean escaped = false; + boolean reject = false; + int tokenstart = -1; + int tokenend = -1; for (int i = 0, length = hdr.length(); i <= length; i++) { - char c = i==length?0:hdr.charAt(i); - - // System.err.printf("i=%d/%d c=%s v=%b q=%b/%b e=%b u=%s s=%d e=%d \t%s=%s%n" ,i,length,c==0?"|":(""+c),invalue,inQuoted,quoted,escaped,unquoted,tokenstart,tokenend,name,value); - + char c = i == length ? 0 : hdr.charAt(i); + // Handle quoted values for name or value if (inQuoted) { + boolean eol = c == 0 && i == hdr.length(); + if (!eol && _compliance != CookieCompliance.RFC2965 && isRFC6265RejectedCharacter(inQuoted, c)) + { + reject = true; + continue; + } + if (escaped) { - escaped=false; - if (c>0) + escaped = false; + if (c > 0) unquoted.append(c); else { @@ -160,7 +167,7 @@ public class CookieCutter } continue; } - + switch (c) { case '"': @@ -175,15 +182,24 @@ public class CookieCutter continue; case 0: - // unterminated quote, let's ignore quotes + // unterminated quote + if (_compliance == CookieCompliance.RFC6265) + continue; + // let's ignore quotes unquoted.setLength(0); inQuoted = false; i--; continue; - + + case ';': + if (_compliance == CookieCompliance.RFC6265) + reject = true; + else + unquoted.append(c); + continue; + default: unquoted.append(c); - continue; } } else @@ -191,7 +207,14 @@ public class CookieCutter // Handle name and value state machines if (invalue) { - // parse the value + boolean eol = c == 0 && i == hdr.length(); + if (!eol && _compliance == CookieCompliance.RFC6265 && isRFC6265RejectedCharacter(inQuoted, c)) + { + reject = true; + continue; + } + + // parse the cookie-value switch (c) { case ' ': @@ -199,19 +222,19 @@ public class CookieCutter break; case ',': - if (_compliance!=CookieCompliance.RFC2965) + if (_compliance != CookieCompliance.RFC2965) { if (quoted) { // must have been a bad internal quote. let's fix as best we can - unquoted.append(hdr,tokenstart,i--); + unquoted.append(hdr, tokenstart, i--); inQuoted = true; quoted = false; continue; } - if (tokenstart<0) + if (tokenstart < 0) tokenstart = i; - tokenend=i; + tokenend = i; continue; } // fall through @@ -226,8 +249,8 @@ public class CookieCutter unquoted.setLength(0); quoted = false; } - else if(tokenstart>=0) - value = tokenend>=tokenstart?hdr.substring(tokenstart, tokenend+1):hdr.substring(tokenstart); + else if (tokenstart >= 0) + value = tokenend >= tokenstart ? hdr.substring(tokenstart, tokenend + 1) : hdr.substring(tokenstart); else value = ""; @@ -235,22 +258,22 @@ public class CookieCutter { if (name.startsWith("$")) { - if (_compliance==CookieCompliance.RFC2965) + if (_compliance == CookieCompliance.RFC2965) { String lowercaseName = name.toLowerCase(Locale.ENGLISH); - switch(lowercaseName) + switch (lowercaseName) { case "$path": - if (cookie!=null) + if (cookie != null) cookie.setPath(value); break; case "$domain": - if (cookie!=null) + if (cookie != null) cookie.setDomain(value); break; case "$port": - if (cookie!=null) - cookie.setComment("$port="+value); + if (cookie != null) + cookie.setComment("$port=" + value); break; case "$version": version = Integer.parseInt(value); @@ -265,7 +288,10 @@ public class CookieCutter cookie = new Cookie(name, value); if (version > 0) cookie.setVersion(version); - cookies.add(cookie); + if (!reject) + { + cookies.add(cookie); + } } } catch (Exception e) @@ -275,46 +301,68 @@ public class CookieCutter name = null; tokenstart = -1; - invalue=false; + invalue = false; + reject = false; break; } case '"': - if (tokenstart<0) + if (tokenstart < 0) { - tokenstart=i; - inQuoted=true; - if (unquoted==null) - unquoted=new StringBuilder(); + tokenstart = i; + inQuoted = true; + if (unquoted == null) + unquoted = new StringBuilder(); break; } + else if (_compliance == CookieCompliance.RFC6265) + { + reject = true; + continue; + } // fall through to default case default: + if (_compliance == CookieCompliance.RFC6265 && quoted) + { + reject = true; + continue; + } + if (quoted) { // must have been a bad internal quote. let's fix as best we can - unquoted.append(hdr,tokenstart,i--); + unquoted.append(hdr, tokenstart, i--); inQuoted = true; quoted = false; continue; } - if (tokenstart<0) + + if (_compliance == CookieCompliance.RFC6265_LEGACY && isRFC6265RejectedCharacter(inQuoted, c)) + reject = true; + + if (tokenstart < 0) tokenstart = i; - tokenend=i; - continue; + tokenend = i; } } else { - // parse the name + // parse the cookie-name switch (c) { case ' ': case '\t': continue; + case ';': + // a cookie terminated with no '=' sign. + tokenstart = -1; + invalue = false; + reject = false; + continue; + case '=': if (quoted) { @@ -322,8 +370,8 @@ public class CookieCutter unquoted.setLength(0); quoted = false; } - else if(tokenstart>=0) - name = tokenend>=tokenstart?hdr.substring(tokenstart, tokenend+1):hdr.substring(tokenstart); + else if (tokenstart >= 0) + name = tokenend >= tokenstart ? hdr.substring(tokenstart, tokenend + 1) : hdr.substring(tokenstart); tokenstart = -1; invalue = true; @@ -333,14 +381,18 @@ public class CookieCutter if (quoted) { // must have been a bad internal quote. let's fix as best we can - unquoted.append(hdr,tokenstart,i--); + unquoted.append(hdr, tokenstart, i--); inQuoted = true; quoted = false; continue; } - if (tokenstart<0) - tokenstart=i; - tokenend=i; + + if (_compliance != CookieCompliance.RFC2965 && isRFC6265RejectedCharacter(inQuoted, c)) + reject = true; + + if (tokenstart < 0) + tokenstart = i; + tokenend = i; continue; } } @@ -348,8 +400,45 @@ public class CookieCutter } } - _cookies = (Cookie[]) cookies.toArray(new Cookie[cookies.size()]); - _lastCookies=_cookies; + _cookies = cookies.toArray(new Cookie[0]); + _lastCookies = _cookies; + } + + + protected boolean isRFC6265RejectedCharacter(boolean inQuoted, char c) + { + // LEGACY test + if (_compliance == CookieCompliance.RFC6265_LEGACY) + { + if (inQuoted) + { + // We only reject if a Control Character is encountered + if (Character.isISOControl(c)) + return true; + } + else + { + return Character.isISOControl(c) || // control characters + c > 127 || // 8-bit characters + c == ',' || // comma + c == ';'; // semicolon + } + return false; + } + + /* From RFC6265 - Section 4.1.1 - Syntax + * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + * ; US-ASCII characters excluding CTLs, + * ; whitespace DQUOTE, comma, semicolon, + * ; and backslash + * + * Note: DQUOTE and semicolon are used as separator by the parser, + * so we can consider them authorized. + */ + return c > 127 || // 8-bit characters + Character.isISOControl(c) || // control characters + c == ',' || // comma + c == '\\'; // backslash } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterTest.java index ec534a1..3e84ce6 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterTest.java @@ -1,6 +1,6 @@ // // ======================================================================== -// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 @@ -18,18 +18,21 @@ package org.eclipse.jetty.server; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - +import java.util.Arrays; +import java.util.List; import javax.servlet.http.Cookie; import org.eclipse.jetty.http.CookieCompliance; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; public class CookieCutterTest { - private Cookie[] parseCookieHeaders(CookieCompliance compliance,String... headers) + private Cookie[] parseCookieHeaders(CookieCompliance compliance, String... headers) { CookieCutter cutter = new CookieCutter(compliance); for (String header : headers) @@ -38,7 +41,7 @@ public class CookieCutterTest } return cutter.getCookies(); } - + private void assertCookie(String prefix, Cookie cookie, String expectedName, String expectedValue, @@ -50,142 +53,174 @@ public class CookieCutterTest assertThat(prefix + ".version", cookie.getVersion(), is(expectedVersion)); assertThat(prefix + ".path", cookie.getPath(), is(expectedPath)); } - + /** * Example from RFC2109 and RFC2965 */ @Test - public void testRFC_Single() + public void testRFCSingle() { String rawCookie = "$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\""; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); - + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + assertThat("Cookies.length", cookies.length, is(1)); assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme"); } - + + /** + * Example from RFC2109 and RFC2965. + * <p> + * Lenient parsing, input has no spaces after ';' token. + * </p> + */ + @Test + public void testRFCSingleLenientNoSpaces() + { + String rawCookie = "$Version=\"1\";Customer=\"WILE_E_COYOTE\";$Path=\"/acme\""; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + + assertThat("Cookies.length", cookies.length, is(1)); + assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme"); + } + /** * Example from RFC2109 and RFC2965 */ @Test - public void testRFC_Double() + public void testRFCDouble() { String rawCookie = "$Version=\"1\"; " + - "Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " + - "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\""; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); - + "Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " + + "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\""; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + assertThat("Cookies.length", cookies.length, is(2)); assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme"); assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 1, "/acme"); } - + /** * Example from RFC2109 and RFC2965 */ @Test - public void testRFC_Triple() + public void testRFCTriple() { String rawCookie = "$Version=\"1\"; " + - "Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " + - "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; " + - "Shipping=\"FedEx\"; $Path=\"/acme\""; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); - + "Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " + + "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; " + + "Shipping=\"FedEx\"; $Path=\"/acme\""; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + assertThat("Cookies.length", cookies.length, is(3)); assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme"); assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 1, "/acme"); assertCookie("Cookies[2]", cookies[2], "Shipping", "FedEx", 1, "/acme"); } - + /** * Example from RFC2109 and RFC2965 */ @Test - public void testRFC_PathExample() + public void testRFCPathExample() { String rawCookie = "$Version=\"1\"; " + - "Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " + - "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\""; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); - + "Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " + + "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\""; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + assertThat("Cookies.length", cookies.length, is(2)); assertCookie("Cookies[0]", cookies[0], "Part_Number", "Riding_Rocket_0023", 1, "/acme/ammo"); assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 1, "/acme"); } - + /** * Example from RFC2109 */ @Test - public void testRFC2109_CookieSpoofingExample() + public void testRFC2109CookieSpoofingExample() { String rawCookie = "$Version=\"1\"; " + - "session_id=\"1234\"; " + - "session_id=\"1111\"; $Domain=\".cracker.edu\""; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); - + "session_id=\"1234\"; " + + "session_id=\"1111\"; $Domain=\".cracker.edu\""; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); + assertThat("Cookies.length", cookies.length, is(2)); assertCookie("Cookies[0]", cookies[0], "session_id", "1234", 1, null); assertCookie("Cookies[1]", cookies[1], "session_id", "1111", 1, null); } - + /** * Example from RFC2965 */ @Test - public void testRFC2965_CookieSpoofingExample() + public void testRFC2965CookieSpoofingExample() { String rawCookie = "$Version=\"1\"; session_id=\"1234\", " + - "$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\""; - - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC2965,rawCookie); + "$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\""; + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie); assertThat("Cookies.length", cookies.length, is(2)); assertCookie("Cookies[0]", cookies[0], "session_id", "1234", 1, null); assertCookie("Cookies[1]", cookies[1], "session_id", "1111", 1, null); - cookies = parseCookieHeaders(CookieCompliance.RFC6265,rawCookie); - assertThat("Cookies.length", cookies.length, is(2)); - assertCookie("Cookies[0]", cookies[0], "session_id", "1234\", $Version=\"1", 0, null); - assertCookie("Cookies[1]", cookies[1], "session_id", "1111", 0, null); + cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + assertThat("Cookies.length", cookies.length, is(1)); + assertCookie("Cookies[0]", cookies[0], "session_id", "1111", 0, null); } - + /** * Example from RFC6265 */ @Test - public void testRFC6265_SidExample() + public void testRFC6265SidExample() { String rawCookie = "SID=31d4d96e407aad42"; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC6265,rawCookie); - + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + assertThat("Cookies.length", cookies.length, is(1)); assertCookie("Cookies[0]", cookies[0], "SID", "31d4d96e407aad42", 0, null); } - + /** * Example from RFC6265 */ @Test - public void testRFC6265_SidLangExample() + public void testRFC6265SidLangExample() { String rawCookie = "SID=31d4d96e407aad42; lang=en-US"; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC6265,rawCookie); - + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + + assertThat("Cookies.length", cookies.length, is(2)); + assertCookie("Cookies[0]", cookies[0], "SID", "31d4d96e407aad42", 0, null); + assertCookie("Cookies[1]", cookies[1], "lang", "en-US", 0, null); + } + + /** + * Example from RFC6265. + * <p> + * Lenient parsing, input has no spaces after ';' token. + * </p> + */ + @Test + public void testRFC6265SidLangExampleLenient() + { + String rawCookie = "SID=31d4d96e407aad42;lang=en-US"; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + assertThat("Cookies.length", cookies.length, is(2)); assertCookie("Cookies[0]", cookies[0], "SID", "31d4d96e407aad42", 0, null); assertCookie("Cookies[1]", cookies[1], "lang", "en-US", 0, null); } - + /** * Basic name=value, following RFC6265 rules */ @@ -193,13 +228,13 @@ public class CookieCutterTest public void testKeyValue() { String rawCookie = "key=value"; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC6265,rawCookie); - + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + assertThat("Cookies.length", cookies.length, is(1)); assertCookie("Cookies[0]", cookies[0], "key", "value", 0, null); } - + /** * Basic name=value, following RFC6265 rules */ @@ -207,9 +242,116 @@ public class CookieCutterTest public void testDollarName() { String rawCookie = "$key=value"; - - Cookie cookies[] = parseCookieHeaders(CookieCompliance.RFC6265,rawCookie); - + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + assertThat("Cookies.length", cookies.length, is(0)); } + + @Test + public void testMultipleCookies() + { + String rawCookie = "testcookie; server.id=abcd; server.detail=cfg"; + + // The first cookie "testcookie" should be ignored, per RFC6265, as it's missing the "=" sign. + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + + assertThat("Cookies.length", cookies.length, is(2)); + assertCookie("Cookies[0]", cookies[0], "server.id", "abcd", 0, null); + assertCookie("Cookies[1]", cookies[1], "server.detail", "cfg", 0, null); + } + + @Test + public void testExcessiveSemicolons() + { + char[] excessive = new char[65535]; + Arrays.fill(excessive, ';'); + String rawCookie = "foo=bar; " + new String(excessive) + "; xyz=pdq"; + + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie); + + assertThat("Cookies.length", cookies.length, is(2)); + assertCookie("Cookies[0]", cookies[0], "foo", "bar", 0, null); + assertCookie("Cookies[1]", cookies[1], "xyz", "pdq", 0, null); + } + + @ParameterizedTest + @MethodSource("rfc6265Cookies") + public void testRFC6265CookieParsing(Param param) + { + Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, param.input); + + assertThat("Cookies.length (" + dump(cookies) + ")", cookies.length, is(param.expected.size())); + for (int i = 0; i < cookies.length; i++) + { + Cookie cookie = cookies[i]; + assertThat("Cookies[" + i + "] (" + dump(cookies) + ")", cookie.getName() + "=" + cookie.getValue(), is(param.expected.get(i))); + } + } + + public static List<Param> rfc6265Cookies() + { + return Arrays.asList( + new Param("A=1; B=2; C=3", "A=1", "B=2", "C=3"), + new Param("A=\"1\"; B=2; C=3", "A=1", "B=2", "C=3"), + new Param("A=\"1\"; B=\"2\"; C=\"3\"", "A=1", "B=2", "C=3"), + new Param("A=1; B=2; C=\"3", "A=1", "B=2"), + new Param("A=1 ; B=2; C=3", "A=1", "B=2", "C=3"), + new Param("A= 1; B=2; C=3", "A=1", "B=2", "C=3"), + new Param("A=\"1; B=2\"; C=3", "C=3"), + new Param("A=\"1; B=2; C=3"), + new Param("A=\"1 B=2\"; C=3", "A=1 B=2", "C=3"), + new Param("A=\"\"1; B=2; C=3", "B=2", "C=3"), + new Param("A=\"\" ; B=2; C=3", "A=", "B=2", "C=3"), + new Param("A=\"\"; B=2; C=3", "A=", "B=2", "C=3"), + new Param("A=1\"\"; B=2; C=3", "B=2", "C=3"), + new Param("A=1\"; B=2; C=3", "B=2", "C=3"), + new Param("A=1\"1; B=2; C=3", "B=2", "C=3"), + new Param("A=\" 1\"; B=2; C=3", "A= 1", "B=2", "C=3"), + new Param("A=\"1 \"; B=2; C=3", "A=1 ", "B=2", "C=3"), + new Param("A=\" 1 \"; B=2; C=3", "A= 1 ", "B=2", "C=3"), + new Param("A=\" 1 1 \"; B=2; C=3", "A= 1 1 ", "B=2", "C=3"), + new Param("A=1,; B=2; C=3", "B=2", "C=3"), + new Param("A=\"1,\"; B=2; C=3", "B=2", "C=3"), + new Param("A=\\1; B=2; C=3", "B=2", "C=3"), + new Param("A=\"\\1\"; B=2; C=3", "B=2", "C=3"), + new Param("A=1\u0007; B=2; C=3", "B=2", "C=3"), + new Param("A=\"1\u0007\"; B=2; C=3", "B=2", "C=3"), + new Param("€"), + new Param("@={}"), + new Param("$X=Y; N=V", "N=V"), + new Param("N=V; $X=Y", "N=V") + ); + } + + private static String dump(Cookie[] cookies) + { + StringBuilder sb = new StringBuilder(); + for (Cookie cookie : cookies) + { + sb.append("<").append(cookie.getName()).append(">=<").append(cookie.getValue()).append("> | "); + } + if (sb.length() > 0) + sb.delete(sb.length() - 2, sb.length() - 1); + return sb.toString(); + } + + private static class Param + { + private final String input; + private final List<String> expected; + + public Param(String input, String... expected) + { + this.input = input; + this.expected = Arrays.asList(expected); + } + + @Override + public String toString() + { + return input + " -> " + expected.toString(); + } + } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 425a9ae..f119864 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -61,6 +61,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import org.eclipse.jetty.http.BadMessageException; +import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.http.MimeTypes; @@ -97,6 +98,7 @@ public class RequestTest http.getHttpConfiguration().setRequestHeaderSize(512); http.getHttpConfiguration().setResponseHeaderSize(512); http.getHttpConfiguration().setOutputBufferSize(2048); + http.getHttpConfiguration().setRequestCookieCompliance(CookieCompliance.RFC6265_LEGACY); http.getHttpConfiguration().addCustomizer(new ForwardedRequestCustomizer()); _connector = new LocalConnector(_server,http); _server.addConnector(_connector);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2