commit 37f622b02d485c52faa15a1ad2a4293a0d9caf76
parent d35af18f06cb7096d1e4c9d3260d6ca53be256d6
Author: Andrea Marchesini <amarchesini@mozilla.com>
Date: Thu, 9 Oct 2025 14:54:32 +0000
Bug 1992536 - Use cookie creation time instead or PR_Now() to validate the expiration time, r=valentin,cookie-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D267977
Diffstat:
6 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/netwerk/cookie/CookieCommons.cpp b/netwerk/cookie/CookieCommons.cpp
@@ -377,7 +377,7 @@ already_AddRefed<Cookie> CookieCommons::CreateCookieFromDocument(
aCookieParser.Parse(baseDomain, requireHostMatch, cookieStatus, cookieString,
EmptyCString(), false, isForeignAndNotAddon,
mustBePartitioned, aDocument->IsInPrivateBrowsing(),
- on3pcbException, PR_Now() / PR_USEC_PER_MSEC);
+ on3pcbException, PR_Now());
if (!aCookieParser.ContainsCookie()) {
return nullptr;
@@ -1023,17 +1023,17 @@ bool CookieCommons::IsSubdomainOf(const nsACString& a, const nsACString& b) {
}
// static
-int64_t CookieCommons::GetCurrentTimeFromChannel(nsIChannel* aChannel) {
+int64_t CookieCommons::GetCurrentTimeInUSecFromChannel(nsIChannel* aChannel) {
nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(aChannel);
if (timedChannel) {
PRTime currentTimeInUSec = 0;
nsresult rv = timedChannel->GetResponseStartTime(¤tTimeInUSec);
if (NS_SUCCEEDED(rv) && currentTimeInUSec) {
- return currentTimeInUSec / PR_USEC_PER_MSEC;
+ return currentTimeInUSec;
}
}
- return PR_Now() / PR_USEC_PER_MSEC;
+ return PR_Now();
}
} // namespace net
diff --git a/netwerk/cookie/CookieCommons.h b/netwerk/cookie/CookieCommons.h
@@ -183,9 +183,9 @@ class CookieCommons final {
// assuming no leading dots are present.
static bool IsSubdomainOf(const nsACString& a, const nsACString& b);
- // Returns the current time in msecs using a nsIChannel, which corresponds to
+ // Returns the current time in USecs using a nsIChannel, which corresponds to
// the response start time.
- static int64_t GetCurrentTimeFromChannel(nsIChannel* aChannel);
+ static int64_t GetCurrentTimeInUSecFromChannel(nsIChannel* aChannel);
};
} // namespace net
diff --git a/netwerk/cookie/CookieParser.cpp b/netwerk/cookie/CookieParser.cpp
@@ -498,9 +498,10 @@ bool CookieParser::ParseMaxAgeAttribute(const nsACString& aMaxage,
bool CookieParser::GetExpiry(CookieStruct& aCookieData,
const nsACString& aExpires,
const nsACString& aMaxage,
- int64_t aCurrentTimeInMSec,
const nsACString& aDateHeader, bool aFromHttp) {
int64_t maxageCap = StaticPrefs::network_cookie_maxageCap();
+ int64_t creationTimeInMSec =
+ aCookieData.creationTime() / int64_t(PR_USEC_PER_MSEC);
/* Determine when the cookie should expire. This is done by taking the
* difference between the server time and the time the server wants the cookie
@@ -516,7 +517,7 @@ bool CookieParser::GetExpiry(CookieStruct& aCookieData,
if (maxage == INT64_MIN) {
aCookieData.expiry() = maxage;
} else {
- CheckedInt<int64_t> value(aCurrentTimeInMSec);
+ CheckedInt<int64_t> value(creationTimeInMSec);
value += (maxageCap ? std::min(maxage, maxageCap) : maxage) * 1000;
aCookieData.expiry() = value.isValid() ? value.value() : INT64_MAX;
@@ -549,7 +550,7 @@ bool CookieParser::GetExpiry(CookieStruct& aCookieData,
StaticPrefs::network_cookie_useServerTime()) {
int64_t serverTimeInMSec =
dateHeaderTimeInUSec / int64_t(PR_USEC_PER_MSEC);
- int64_t delta = aCurrentTimeInMSec - serverTimeInMSec;
+ int64_t delta = creationTimeInMSec - serverTimeInMSec;
expiresInMSec += delta;
}
}
@@ -561,7 +562,7 @@ bool CookieParser::GetExpiry(CookieStruct& aCookieData,
// The cookie item have to be used to the expired cookie.
aCookieData.expiry() =
- CookieCommons::MaybeCapExpiry(aCurrentTimeInMSec, expiresInMSec);
+ CookieCommons::MaybeCapExpiry(creationTimeInMSec, expiresInMSec);
return false;
}
@@ -656,11 +657,13 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
const nsACString& aDateHeader, bool aFromHttp,
bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing, bool aOn3pcbException,
- int64_t aCurrentTimeInMSec) {
+ int64_t aCurrentTimeInUSec) {
MOZ_ASSERT(!mValidation);
// init expiryTime such that session cookies won't prematurely expire
mCookieData.expiry() = INT64_MAX;
+ mCookieData.creationTime() =
+ Cookie::GenerateUniqueCreationTime(aCurrentTimeInUSec);
mCookieData.schemeMap() = CookieCommons::URIToSchemeType(mHostURI);
@@ -679,8 +682,8 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
}
// calculate expiry time of cookie.
- mCookieData.isSession() = GetExpiry(
- mCookieData, expires, maxage, aCurrentTimeInMSec, aDateHeader, aFromHttp);
+ mCookieData.isSession() =
+ GetExpiry(mCookieData, expires, maxage, aDateHeader, aFromHttp);
if (aStatus == STATUS_ACCEPT_SESSION) {
// force lifetime to session. note that the expiration time, if set above,
// will still apply.
diff --git a/netwerk/cookie/CookieParser.h b/netwerk/cookie/CookieParser.h
@@ -70,10 +70,10 @@ class CookieParser final {
void ParseAttributes(nsCString& aCookieHeader, nsACString& aExpires,
nsACString& aMaxage, bool& aAcceptedByParser);
- // aCurrentTime is in milliseconds, and expiry will be stored in milliseconds.
+ // expiry will be stored in milliseconds.
bool GetExpiry(CookieStruct& aCookieData, const nsACString& aExpires,
- const nsACString& aMaxage, int64_t aCurrentTime,
- const nsACString& aDateHeader, bool aFromHttp);
+ const nsACString& aMaxage, const nsACString& aDateHeader,
+ bool aFromHttp);
static bool CheckAttributeSize(const nsACString& currentValue,
const char* aAttribute,
diff --git a/netwerk/cookie/CookieService.cpp b/netwerk/cookie/CookieService.cpp
@@ -588,7 +588,7 @@ CookieService::SetCookieStringFromHttp(nsIURI* aHostURI,
dateHeader, true, isForeignAndNotAddon, mustBePartitioned,
storagePrincipalOriginAttributes.IsPrivateBrowsing(),
loadInfo->GetIsOn3PCBExceptionList(),
- CookieCommons::GetCurrentTimeFromChannel(aChannel));
+ CookieCommons::GetCurrentTimeInUSecFromChannel(aChannel));
if (!cookieParser.ContainsCookie()) {
return NS_OK;
diff --git a/netwerk/cookie/CookieValidation.cpp b/netwerk/cookie/CookieValidation.cpp
@@ -115,7 +115,7 @@ void CookieValidation::ValidateInternal() {
// This part checks if the caleers have set the expiry value to max 400 days.
if (!mCookieData.isSession()) {
int64_t maxageCap = StaticPrefs::network_cookie_maxageCap();
- int64_t currentTimeInMSec = PR_Now() / PR_USEC_PER_MSEC;
+ int64_t currentTimeInMSec = mCookieData.creationTime() / PR_USEC_PER_MSEC;
int64_t expiry = mCookieData.expiry();
if (maxageCap && expiry > currentTimeInMSec + maxageCap * 1000) {
mResult = eRejectedAttributeExpiryOversize;