net: Keep IP cookie buckets separate (#44152)

Use the full IP address as the cookie storage bucket key instead of
passing IP hosts through the public suffix registrable-domain helper.
This prevents unrelated IP hosts that share suffix-like address segments
from sharing a per-host eviction bucket.

Testing: Added `test_ip_cookie_bucket_collision_eviction`; ran `cargo
test -p servo-net --test main test_ip_cookie_bucket_collision_eviction
--locked`.
Fixes: #44097

---------

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
This commit is contained in:
Asish Kumar
2026-04-19 01:25:19 +05:30
committed by GitHub
parent 39a3aa991f
commit 678f9d7a47
2 changed files with 39 additions and 0 deletions

View File

@@ -8,6 +8,7 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::net::IpAddr;
use std::time::SystemTime;
use cookie::Cookie;
@@ -292,6 +293,14 @@ impl CookieStorage {
}
fn reg_host(url: &str) -> String {
let host_for_ip_parse = url
.strip_prefix('[')
.and_then(|url| url.strip_suffix(']'))
.unwrap_or(url);
if let Ok(address) = host_for_ip_parse.parse::<IpAddr>() {
return address.to_string().to_lowercase();
}
reg_suffix(url).to_lowercase()
}

View File

@@ -222,6 +222,36 @@ fn add_cookie_to_storage(storage: &mut CookieStorage, url: &ServoUrl, cookie_str
storage.push(cookie, url, source);
}
fn assert_ip_cookie_bucket_collision_eviction(ip_a: &str, ip_b: &str) {
let mut storage = CookieStorage::new(5);
let ip_a = ServoUrl::parse(ip_a).unwrap();
let ip_b = ServoUrl::parse(ip_b).unwrap();
let source = CookieSource::HTTP;
for i in 1..=3 {
add_cookie_to_storage(&mut storage, &ip_a, &format!("a{i}=val{i}"));
}
for i in 1..=5 {
add_cookie_to_storage(&mut storage, &ip_b, &format!("b{i}=val{i}"));
}
let cookies_a = storage.cookies_for_url(&ip_a, source).unwrap();
assert_eq!(cookies_a.split("; ").count(), 3);
for i in 1..=3 {
assert!(cookies_a.contains(&format!("a{i}=val{i}")));
}
}
#[test]
fn test_ip_cookie_bucket_collision_eviction() {
assert_ip_cookie_bucket_collision_eviction("http://192.168.0.1/path", "http://10.0.0.1/path");
assert_ip_cookie_bucket_collision_eviction(
"http://[2001:db8::1]/path",
"http://[2001:db8::2]/path",
);
}
#[test]
fn test_insecure_cookies_cannot_evict_secure_cookie() {
let mut storage = CookieStorage::new(5);