1 Star 0 Fork 15

starlet_dx/jetty

forked from src-openEuler/jetty 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
CVE-2023-26049.patch 33.46 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
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);
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/starlet-dx/jetty.git
git@gitee.com:starlet-dx/jetty.git
starlet-dx
jetty
jetty
master

搜索帮助