Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit e29f0dc

Browse files
authored
Fix Set-Cookie header parsing in CookieContainer (#26005)
* fix cookie container set-cookie parsing * fix spacing * fix format * address feedback
1 parent 4d2e6f6 commit e29f0dc

File tree

3 files changed

+143
-8
lines changed

3 files changed

+143
-8
lines changed

src/Common/src/System/Net/CookieParser.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,5 +905,10 @@ internal static string CheckQuoted(string value)
905905

906906
return value.Length == 2 ? string.Empty : value.Substring(1, value.Length - 2);
907907
}
908+
909+
internal bool EndofHeader()
910+
{
911+
return _tokenizer.Eof;
912+
}
908913
}
909914
}

src/System.Net.Primitives/src/System/Net/CookieContainer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,11 @@ internal CookieCollection CookieCutter(Uri uri, string headerName, string setCoo
675675

676676
if (cookie == null)
677677
{
678-
break;
678+
if (parser.EndofHeader())
679+
{
680+
break;
681+
}
682+
continue;
679683
}
680684

681685
// Parser marks invalid cookies this way

src/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs

Lines changed: 133 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ public static IEnumerable<object[]> SetCookiesData()
143143
}
144144
}; // RFC 2965
145145

146-
yield return new object[] { u,
146+
yield return new object[]
147+
{
148+
u,
147149
"name98=value98; port=\"80, 90\", name99=value99",
148150
new Cookie[]
149151
{
@@ -152,7 +154,8 @@ public static IEnumerable<object[]> SetCookiesData()
152154
}
153155
}; // RFC 2965 (no path)
154156

155-
yield return new object[] {
157+
yield return new object[]
158+
{
156159
uSecure,
157160
"name98=value98; name98=value98; comment=comment; comment=comment2; commentURL=http://url.com; commentURL=commentURL2; discard; discard; domain=.uri.com; domain=domain2; max-age=400; max-age=400; path=/; path=path; port=\"80, 90, 443\"; port=port2; path=path; expires=Wed, 09 Jun 2021 10:18:14 GMT; expires=expires2; secure; secure; httponly; httponly; Version=100; Version=100, name99=value99",
158161
new Cookie[]
@@ -162,7 +165,8 @@ public static IEnumerable<object[]> SetCookiesData()
162165
}
163166
}; // Double entries
164167

165-
yield return new object[] {
168+
yield return new object[]
169+
{
166170
u,
167171
"name98=value98; commentURL=invalidurl",
168172
new Cookie[]
@@ -171,7 +175,8 @@ public static IEnumerable<object[]> SetCookiesData()
171175
}
172176
}; // Ignore invalid comment url
173177

174-
yield return new object[] {
178+
yield return new object[]
179+
{
175180
u6,
176181
"name98=value98; unknown1; unknown2=unknown",
177182
new Cookie[]
@@ -180,7 +185,8 @@ public static IEnumerable<object[]> SetCookiesData()
180185
}
181186
}; // Ignore unknown tokens
182187

183-
yield return new object[] {
188+
yield return new object[]
189+
{
184190
u6,
185191
"name98=value98; =; token=",
186192
new Cookie[]
@@ -189,7 +195,8 @@ public static IEnumerable<object[]> SetCookiesData()
189195
}
190196
}; // Ignore invalid tokens
191197

192-
yield return new object[] {
198+
yield return new object[]
199+
{
193200
u6,
194201
"name98=\"value; domain=\".domain\"; max-age=\"400\"",
195202
new Cookie[]
@@ -198,14 +205,132 @@ public static IEnumerable<object[]> SetCookiesData()
198205
}
199206
}; // Use escaped values (1)
200207

201-
yield return new object[] {
208+
yield return new object[]
209+
{
202210
u6,
203211
"name98=\"\"",
204212
new Cookie[]
205213
{
206214
new Cookie("name98", "\"\"")
207215
}
208216
}; // Use escaped values (2)
217+
218+
yield return new object[]
219+
{
220+
u,
221+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1",
222+
new Cookie[]
223+
{
224+
new Cookie("locale", "en"),
225+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
226+
new Cookie("country", "US"),
227+
new Cookie("_m_ask_fm_session", "session1")
228+
}
229+
}; // Normal case
230+
231+
yield return new object[]
232+
{
233+
uSecure,
234+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1",
235+
new Cookie[]
236+
{
237+
new Cookie("locale", "en"),
238+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
239+
new Cookie("country", "US"),
240+
new Cookie("_m_ask_fm_session", "session1")
241+
}
242+
}; // Normal case with secure URI
243+
244+
yield return new object[]
245+
{
246+
u,
247+
",locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1",
248+
new Cookie[]
249+
{
250+
new Cookie("locale", "en"),
251+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
252+
new Cookie("country", "US"),
253+
new Cookie("_m_ask_fm_session", "session1")
254+
}
255+
}; // Empty header at the beginning
256+
257+
yield return new object[]
258+
{
259+
uSecure,
260+
" ,locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1",
261+
new Cookie[]
262+
{
263+
new Cookie("locale", "en"),
264+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
265+
new Cookie("country", "US"),
266+
new Cookie("_m_ask_fm_session", "session1")
267+
}
268+
}; // Empty header composed of spaces at the beginning
269+
270+
yield return new object[]
271+
{
272+
u,
273+
"locale=en,, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1",
274+
new Cookie[]
275+
{
276+
new Cookie("locale", "en"),
277+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
278+
new Cookie("country", "US"),
279+
new Cookie("_m_ask_fm_session", "session1")
280+
}
281+
}; // Empty header in the middle
282+
283+
yield return new object[]
284+
{
285+
uSecure,
286+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, , country=US, _m_ask_fm_session=session1",
287+
new Cookie[]
288+
{
289+
new Cookie("locale", "en"),
290+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
291+
new Cookie("country", "US"),
292+
new Cookie("_m_ask_fm_session", "session1")
293+
}
294+
}; // Empty header composed of spaces in the middle
295+
296+
yield return new object[]
297+
{
298+
u,
299+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1,",
300+
new Cookie[]
301+
{
302+
new Cookie("locale", "en"),
303+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
304+
new Cookie("country", "US"),
305+
new Cookie("_m_ask_fm_session", "session1")
306+
}
307+
}; // Empty header at the end
308+
309+
yield return new object[]
310+
{
311+
u,
312+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1, ",
313+
new Cookie[]
314+
{
315+
new Cookie("locale", "en"),
316+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
317+
new Cookie("country", "US"),
318+
new Cookie("_m_ask_fm_session", "session1")
319+
}
320+
}; // Empty header composed of spaces at the end
321+
322+
yield return new object[]
323+
{
324+
uSecure,
325+
"locale=en, uuid=4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46, country=US, _m_ask_fm_session=session1, ,",
326+
new Cookie[]
327+
{
328+
new Cookie("locale", "en"),
329+
new Cookie("uuid", "4b8b2dd7-d91a-49ee-80c6-8cb7df1fae46"),
330+
new Cookie("country", "US"),
331+
new Cookie("_m_ask_fm_session", "session1")
332+
}
333+
}; // Empty header followed by another empty header at the end
209334
}
210335

211336
[Theory]
@@ -218,6 +343,7 @@ public void GetCookieHeader_Success(Uri uri, string expected)
218343

219344
[Theory]
220345
[MemberData(nameof(SetCookiesData))]
346+
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Requires fix shipping in .NET 4.7.2")]
221347
public void SetCookies_Success(Uri uri, string cookieHeader, Cookie[] expected)
222348
{
223349
CookieContainer cc = CreateCount11Container();

0 commit comments

Comments
 (0)