From f09a33a9e1320cf6e022b0ef455982a6f31640e4 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:29:28 +0000 Subject: [PATCH] fix(rust-gateway): reject OCR timeouts that overflow Duration Guard the OCR timeout against values that pass the finite/positive check but exceed Duration's range (e.g. 1e300), which previously panicked in Duration::from_secs_f64; use try_from_secs_f64 and return a typed 400. Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com> --- .../ai-gateway/src/routes/ocr/transport.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/litellm-rust/crates/ai-gateway/src/routes/ocr/transport.rs b/litellm-rust/crates/ai-gateway/src/routes/ocr/transport.rs index 66a9e7b5ef1..5c3132cd492 100644 --- a/litellm-rust/crates/ai-gateway/src/routes/ocr/transport.rs +++ b/litellm-rust/crates/ai-gateway/src/routes/ocr/transport.rs @@ -58,13 +58,17 @@ pub struct OcrCall { } fn parse_timeout(seconds: Option) -> CoreResult> { - match seconds { - None => Ok(None), - Some(value) if value.is_finite() && value > 0.0 => Ok(Some(Duration::from_secs_f64(value))), - Some(_) => Err(CoreError::InvalidRequest( + let Some(value) = seconds else { + return Ok(None); + }; + if !value.is_finite() || value <= 0.0 { + return Err(CoreError::InvalidRequest( "'timeout' must be a positive, finite number of seconds".to_string(), - )), + )); } + Duration::try_from_secs_f64(value).map(Some).map_err(|_| { + CoreError::InvalidRequest("'timeout' is larger than the supported range".to_string()) + }) } fn reject_reserved_params<'a>(names: impl IntoIterator) -> CoreResult<()> { @@ -451,7 +455,7 @@ mod tests { #[test] fn json_rejects_non_positive_timeout() { - for timeout in ["0", "-1", "-0.5"] { + for timeout in ["0", "-1", "-0.5", "1e300"] { let body = format!( r#"{{"model":"m","document":{{"type":"document_url","document_url":"https://x"}},"timeout":{timeout}}}"# ); @@ -468,7 +472,7 @@ mod tests { #[test] fn multipart_rejects_non_positive_and_non_finite_timeout() { let document = json!({"type": "document_url", "document_url": "data:x"}); - for timeout in ["0", "-3", "inf", "-inf", "NaN"] { + for timeout in ["0", "-3", "inf", "-inf", "NaN", "1e300"] { let fields = vec![ ("model".to_string(), "m".to_string()), ("timeout".to_string(), timeout.to_string()),