mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-25 10:23:32 +00:00
8380549: HttpCookie.expiryDate2DeltaSeconds returns 0 on parse failure, causing immediate cookie expiration
Reviewed-by: vyazici, michaelm
This commit is contained in:
parent
2b05a136cb
commit
f146847ca1
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1005,12 +1005,13 @@ public final class HttpCookie implements Cloneable {
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
|
||||
try {
|
||||
if (expiresValue != null) {
|
||||
long delta = cookie.expiryDate2DeltaSeconds(expiresValue);
|
||||
if (expiresValue != null) {
|
||||
Calendar cal = parseExpires(expiresValue);
|
||||
if (cal != null) {
|
||||
long delta = (cal.getTimeInMillis() - cookie.whenCreated) / 1000;
|
||||
cookie.maxAge = (delta > 0 ? delta : 0);
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assignAttribute(HttpCookie cookie,
|
||||
@ -1082,10 +1083,10 @@ public final class HttpCookie implements Cloneable {
|
||||
* @param dateString
|
||||
* a date string in one of the formats defined in Netscape cookie spec
|
||||
*
|
||||
* @return delta seconds between this cookie's creation time and the time
|
||||
* specified by dateString
|
||||
* @return the parsed date as a Calendar, or null if none of the
|
||||
* formats could parse the given date string
|
||||
*/
|
||||
private long expiryDate2DeltaSeconds(String dateString) {
|
||||
private static Calendar parseExpires(String dateString) {
|
||||
Calendar cal = new GregorianCalendar(GMT);
|
||||
for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
|
||||
SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i],
|
||||
@ -1108,12 +1109,12 @@ public final class HttpCookie implements Cloneable {
|
||||
}
|
||||
cal.set(Calendar.YEAR, year);
|
||||
}
|
||||
return (cal.getTimeInMillis() - whenCreated) / 1000;
|
||||
return cal;
|
||||
} catch (Exception e) {
|
||||
// Ignore, try the next date format
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,7 @@
|
||||
/**
|
||||
* @test
|
||||
* @bug 6791927 8233886
|
||||
* @summary Wrong Locale in HttpCookie::expiryDate2DeltaSeconds
|
||||
* @summary Wrong Locale in HttpCookie::parseExpires
|
||||
* @run main/othervm B6791927
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8000525
|
||||
* @bug 8000525 8380549
|
||||
* @library /test/lib
|
||||
*/
|
||||
|
||||
@ -33,6 +33,8 @@ import java.io.*;
|
||||
import java.text.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
import static jdk.test.lib.Asserts.assertEquals;
|
||||
|
||||
public class ExpiredCookieTest {
|
||||
// lifted from HttpCookie.java
|
||||
private final static String[] COOKIE_DATE_FORMATS = {
|
||||
@ -92,15 +94,28 @@ public class ExpiredCookieTest {
|
||||
cm.put(uri, header);
|
||||
|
||||
CookieStore cookieJar = cm.getCookieStore();
|
||||
List <HttpCookie> cookies = cookieJar.getCookies();
|
||||
Set<String> names = new TreeSet<>();
|
||||
for (HttpCookie cookie : cookieJar.getCookies())
|
||||
names.add(cookie.getName());
|
||||
|
||||
Set<String> expected;
|
||||
if (COOKIE_DATE_FORMATS[i].contains("yyyy")) {
|
||||
if (cookies.size() != 2)
|
||||
throw new RuntimeException(
|
||||
"Incorrectly parsing a bad date");
|
||||
} else if (cookies.size() != 1) {
|
||||
throw new RuntimeException(
|
||||
"Incorrectly parsing a bad date");
|
||||
// Four-digit years parse unambiguously: TEST1 and TEST2 are
|
||||
// in the past and expire, while TEST3 and TEST4 remain.
|
||||
expected = new TreeSet<>(List.of("TEST3", "TEST4"));
|
||||
} else {
|
||||
// Two-digit years make TEST2 and TEST3 resolve to a mismatched
|
||||
// day-of-week, so strict parsing rejects the Expires value; per
|
||||
// RFC 6265 section 5.2.1 an unparseable Expires is ignored, so
|
||||
// they remain as session cookies. TEST1 parses cleanly but is
|
||||
// already expired, so it is dropped. TEST4's two-digit year
|
||||
// round-trips to itself (69 -> 2069), so it parses and remains
|
||||
// because its expiry is still in the future.
|
||||
expected = new TreeSet<>(List.of("TEST2", "TEST3", "TEST4"));
|
||||
}
|
||||
assertEquals(expected, names,
|
||||
"Incorrectly parsing a bad date, format: "
|
||||
+ COOKIE_DATE_FORMATS[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class MaxAgeExpires {
|
||||
|
||||
@ -138,4 +139,26 @@ public class MaxAgeExpires {
|
||||
cookie.setMaxAge(-2);
|
||||
assertEquals(-2, cookie.getMaxAge());
|
||||
}
|
||||
|
||||
public static Object[][] unparseableDates() {
|
||||
return new Object[][] {
|
||||
{ "GARBAGE" },
|
||||
{ "2024-01-01T00:00:00Z" }, // format not supported by RFC-6265
|
||||
{ "January 1, 2099 00:00:00 GMT" } // format not supported by RFC-6265
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("unparseableDates")
|
||||
public void testUnparseableExpires(String badDate) {
|
||||
// RFC 6265 section 5.2.1: if the expires value fails to parse,
|
||||
// the cookie-av should be ignored.
|
||||
// That results in the HttpCookie implementation to have maxAge value of -1.
|
||||
HttpCookie cookie = HttpCookie.parse(
|
||||
"Set-Cookie: name=value; expires=" + badDate).get(0);
|
||||
assertEquals(-1, cookie.getMaxAge(),
|
||||
"Unparseable expires=\"" + badDate + "\" should be ignored");
|
||||
assertFalse(cookie.hasExpired(),
|
||||
"Cookie with ignored expires should not be expired");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user