fix(analysis): cap OCR decoded pixels to stop decompression-bomb OOM
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -202,6 +202,13 @@ pub struct AnalysisConfig {
|
||||
/// Hard cap on a page image's stored size; larger pages are skipped
|
||||
/// (`ANALYSIS_MAX_IMAGE_BYTES`).
|
||||
pub max_image_bytes: usize,
|
||||
/// Hard cap on a page image's **decoded** pixel count for the OCR backend
|
||||
/// (`ANALYSIS_OCR_MAX_DECODE_PIXELS`). `max_image_bytes` only bounds the
|
||||
/// *encoded* size; without a decode bound a tiny image declaring
|
||||
/// 50000×50000 inflates to billions of bytes and OOM-kills the worker
|
||||
/// (decompression bomb). Generous by default (100 MP) so legitimately
|
||||
/// tall, un-sliced manga pages still decode.
|
||||
pub ocr_max_decode_pixels: u64,
|
||||
/// Output-constraint mode (`ANALYSIS_RESPONSE_FORMAT`):
|
||||
/// `json_schema` (default) | `json_object` | `none`.
|
||||
pub response_format: ResponseFormat,
|
||||
@@ -251,6 +258,7 @@ impl Default for AnalysisConfig {
|
||||
tall_aspect_threshold: 1.6,
|
||||
max_slices: 16,
|
||||
max_image_bytes: 8 * 1024 * 1024,
|
||||
ocr_max_decode_pixels: 100_000_000,
|
||||
response_format: ResponseFormat::JsonSchema,
|
||||
frequency_penalty: 0.3,
|
||||
temperature: 0.0,
|
||||
@@ -327,6 +335,10 @@ impl AnalysisConfig {
|
||||
.max(1.0),
|
||||
max_slices: env_usize("ANALYSIS_MAX_SLICES", d.max_slices).max(1),
|
||||
max_image_bytes: env_usize("ANALYSIS_MAX_IMAGE_BYTES", d.max_image_bytes),
|
||||
ocr_max_decode_pixels: env_u64(
|
||||
"ANALYSIS_OCR_MAX_DECODE_PIXELS",
|
||||
d.ocr_max_decode_pixels,
|
||||
),
|
||||
response_format: std::env::var("ANALYSIS_RESPONSE_FORMAT")
|
||||
.map(|s| ResponseFormat::from_str(&s))
|
||||
.unwrap_or(d.response_format),
|
||||
|
||||
Reference in New Issue
Block a user