diff --git a/codex-rs/code-mode-protocol/src/wire.rs b/codex-rs/code-mode-protocol/src/wire.rs index 7a637cb767..dbaf64ab2d 100644 --- a/codex-rs/code-mode-protocol/src/wire.rs +++ b/codex-rs/code-mode-protocol/src/wire.rs @@ -16,7 +16,10 @@ use crate::RuntimeResponse; use crate::WaitOutcome; use crate::WaitRequest; -const MAX_FRAME_BYTES: usize = 16 * 1024 * 1024; +// Keep allocations from untrusted frame lengths bounded while leaving enough +// room for large inline image results. These are base64 encoded and can easily +// exceed the previous 16 MiB limit before downstream output truncation runs. +const MAX_FRAME_BYTES: usize = 256 * 1024 * 1024; pub type RequestId = u64; pub type SessionId = u64; diff --git a/codex-rs/code-mode-protocol/src/wire_tests.rs b/codex-rs/code-mode-protocol/src/wire_tests.rs index 61b672063b..4a8f20cfe3 100644 --- a/codex-rs/code-mode-protocol/src/wire_tests.rs +++ b/codex-rs/code-mode-protocol/src/wire_tests.rs @@ -1,7 +1,9 @@ +use tokio::io::AsyncWriteExt; use tokio::io::duplex; use super::ClientMessage; use super::HostRequest; +use super::MAX_FRAME_BYTES; use super::read_frame; use super::write_frame; @@ -26,3 +28,32 @@ async fn frame_round_trip_preserves_message() { }) )); } + +#[tokio::test] +async fn frame_round_trip_supports_payloads_larger_than_sixteen_mib() { + let (mut client, mut server) = duplex(64 * 1024); + let payload = "x".repeat(17 * 1024 * 1024); + + let (write_result, read_result) = tokio::join!( + write_frame(&mut client, &payload), + read_frame::<_, String>(&mut server), + ); + + write_result.expect("write frame"); + assert_eq!(read_result.expect("read frame"), Some(payload)); +} + +#[tokio::test] +async fn read_frame_rejects_lengths_above_allocation_limit() { + let (mut client, mut server) = duplex(16); + client + .write_u32(u32::try_from(MAX_FRAME_BYTES + 1).expect("frame limit fits in u32")) + .await + .expect("write frame length"); + + let error = read_frame::<_, String>(&mut server) + .await + .expect_err("reject oversized frame"); + + assert_eq!(error.kind(), std::io::ErrorKind::InvalidData); +}