Problem
src/cookies.rs:203-206 replaces a cookie with the same name/domain/path using self.cookies.remove(i) followed by self.cookies.push(cookie), which moves the replacement to the end of the vec. RFC 6265 §5.3 step 11.3 says the new cookie inherits the old one's creation-time, and §5.4 uses creation-time to break ties between cookies of equal path length. The comment at :248 relies on exactly that:
// §5.4: longer paths first. `sort_by_key` is stable, so cookies
// with equal path length keep the order they were set in, which is the
// spec's creation-time tiebreak.
The stable sort does preserve vec order, but vec order stops being creation order as soon as a reset happens:
hop1 sets a=1, b=1 ; hop2 resets a=2
next hop gets: "b=1; a=2" // expected "a=2; b=1"
It bites hardest when one name is held at two scopes (host-only plus Domain-wide), which is a normal pattern. After a reset the duplicate pair flips to s=domainwide; s=hostonly2, so a server that takes the first occurrence reads the stale value instead of the one the site just issued.
Proposed Solution
Assign in place, self.cookies[i] = cookie;, instead of remove-then-push, so the replacement keeps the incumbent's slot and the stable sort's tiebreak stays a real creation-time tiebreak.
Found by @en0f while reviewing #86.
Problem
src/cookies.rs:203-206replaces a cookie with the same name/domain/path usingself.cookies.remove(i)followed byself.cookies.push(cookie), which moves the replacement to the end of the vec. RFC 6265 §5.3 step 11.3 says the new cookie inherits the old one's creation-time, and §5.4 uses creation-time to break ties between cookies of equal path length. The comment at:248relies on exactly that:The stable sort does preserve vec order, but vec order stops being creation order as soon as a reset happens:
It bites hardest when one name is held at two scopes (host-only plus
Domain-wide), which is a normal pattern. After a reset the duplicate pair flips tos=domainwide; s=hostonly2, so a server that takes the first occurrence reads the stale value instead of the one the site just issued.Proposed Solution
Assign in place,
self.cookies[i] = cookie;, instead of remove-then-push, so the replacement keeps the incumbent's slot and the stable sort's tiebreak stays a real creation-time tiebreak.Found by @en0f while reviewing #86.