fix(servo): bound live protocol metadata

This commit is contained in:
2026-07-09 23:32:17 -04:00
parent a6e3aeaf46
commit 83badaea81
13 changed files with 482 additions and 68 deletions
+75
View File
@@ -190,6 +190,81 @@ fn live_sidecar_rejects_oversized_frame_dimensions() -> Result<(), Box<dyn Error
Ok(())
}
#[test]
fn live_sidecar_rejects_overlong_request_url_without_exiting() -> Result<(), Box<dyn Error>> {
let root = TestDirectory::new()?;
let profile_id = ProfileId::new();
let tab_id = TabId::new();
let mut sidecar = Sidecar::spawn(root.path())?;
let overlong_url = format!("https://example.com/{}", "a".repeat(32 * 1024));
let response = sidecar.exchange(&ensure_request(&tab_id, &profile_id, &overlong_url))?;
assert!(response.frame.is_none());
assert!(
response
.error
.as_deref()
.is_some_and(|error| error == "request URL exceeds the 32768-byte live protocol limit")
);
sidecar.shutdown()?;
Ok(())
}
#[test]
fn live_sidecar_retires_a_session_with_an_overlong_loaded_url() -> Result<(), Box<dyn Error>> {
let server = TestServer::start()?;
let root = TestDirectory::new()?;
let profile_id = ProfileId::new();
let tab_id = TabId::new();
let mut sidecar = Sidecar::spawn(root.path())?;
let mut response = sidecar.exchange(&ensure_request(
&tab_id,
&profile_id,
&server.url("/oversized-history"),
))?;
let started_at = Instant::now();
loop {
if response.error.as_deref()
== Some("loaded URL exceeds the 32768-byte live protocol limit")
{
assert!(response.frame.is_none());
break;
}
if started_at.elapsed() >= RESPONSE_TIMEOUT {
return Err(io::Error::new(
io::ErrorKind::TimedOut,
"timed out waiting for oversized loaded URL rejection",
)
.into());
}
thread::sleep(Duration::from_millis(2));
response = sidecar.exchange(&json!({ "type": "poll", "tab_id": tab_id.as_str() }))?;
}
let mut response =
sidecar.exchange(&ensure_request(&tab_id, &profile_id, &server.url("/white")))?;
let started_at = Instant::now();
while response.frame.as_ref().and_then(|frame| frame.title.as_deref()) != Some("white-ready") {
if let Some(error) = response.error {
return Err(io::Error::other(format!("replacement session failed: {error}")).into());
}
if started_at.elapsed() >= RESPONSE_TIMEOUT {
return Err(io::Error::new(
io::ErrorKind::TimedOut,
"timed out waiting for replacement session",
)
.into());
}
thread::sleep(Duration::from_millis(2));
response = sidecar.exchange(&json!({ "type": "poll", "tab_id": tab_id.as_str() }))?;
}
sidecar.shutdown()?;
Ok(())
}
#[test]
fn live_sidecar_rejects_duplicate_permission_snapshot_entries() -> Result<(), Box<dyn Error>> {
let root = TestDirectory::new()?;
@@ -465,6 +465,8 @@ fn serve_connection(
SET_PAGE
} else if path.starts_with("/history") {
HISTORY_PAGE
} else if path == "/oversized-history" {
OVERSIZED_HISTORY_PAGE
} else if path == "/white" {
WHITE_PAGE
} else {
@@ -486,4 +488,6 @@ const READ_PAGE: &str = r#"<!doctype html><title>loading</title><style>body{font
const HISTORY_PAGE: &str = r#"<!doctype html><title>loading</title><style>body{font:24px sans-serif;color:#111;background:#fff}</style><body>History mutation</body><script>history.replaceState({},'', '/history?state=1');document.title='history-ready';</script>"#;
const OVERSIZED_HISTORY_PAGE: &str = r#"<!doctype html><title>oversized-history</title><script>history.replaceState({},'', '/oversized?' + 'a'.repeat(32768));</script>"#;
const WHITE_PAGE: &str = r#"<!doctype html><title>white-ready</title><style>html,body{margin:0;width:100%;height:100%;background:#fff}</style>"#;