srujana-kuntumalla opened a new pull request, #3009: URL: https://github.com/apache/tika/pull/3009
## Summary Follow-on to the earlier TIKA-4793 configurable-payload-limit work. Four issues were found after that PR: - **OOM in forked JVM for large documents** (e.g. 500 MB text with uncapped `maxIpcPayloadBytes`): `ServerProtocolIO.writeFinished()` called `JsonPipesIpc.toBytes()` unconditionally, allocating a full Smile `byte[]` in one shot. For large content this exhausted heap. - **Heap-bound error on very large single files**: Same root cause — Jackson's `ByteArrayBuilder` cannot produce a `byte[]` > 2 GB, so content that serializes beyond that limit caused `OutOfMemoryError` inside `toBytes()`. - **PDF "truncation" past ~80 M chars**: For Unicode-heavy PDFs, 80 M chars × 3 bytes/char UTF-8 Smile exceeds the 100 MB default limit. Previously the server wrote the oversized payload anyway, the client threw `PayloadLimitExceededException`, the IPC stream desynced, and the connection was torn down. Users saw "no content returned" and interpreted it as truncation. - **7z / rar / iso DYNAMIC emit-strategy sizing**: `EmitDataImpl.estimateSizeInBytes()` used `length × 2` (Java UTF-16 heap cost), but the DYNAMIC threshold is in wire bytes (Smile UTF-8). ASCII-heavy archive metadata (file paths, checksums, MIME types) encodes at ~1 byte/char, so estimates were 2× too high and compressed-archive results were incorrectly routed to direct-emit. ## Changes **`ServerProtocolIO`** — three-layer guard in `writeFinished()`: 1. **Pre-check**: if `getEstimatedSizeBytes() > maxPayloadBytes`, skip serialization entirely (prevents OOM before any allocation). 2. **OOM catch**: wraps `JsonPipesIpc.toBytes()` — caught `OutOfMemoryError` frees the byte-builder segments; the tiny `PAYLOAD_LIMIT_EXCEEDED` response then serializes cleanly. 3. **Post-check**: if serialized `bytes.length > maxPayloadBytes` (CJK-heavy content where the 1 byte/char pre-estimate is optimistic), discard server-side — client sees a clean `PAYLOAD_LIMIT_EXCEEDED`, no stream desync. Constructor now takes `maxPayloadBytes` explicitly. **`PipesServer` / `ConnectionHandler`** — pass `pipesConfig.getMaxIpcPayloadBytes()` to `ServerProtocolIO` (one line each). **`EmitDataImpl.estimateSizeInBytes()`** — change multiplier from `length × 2` to `length` (1 byte/char ≈ Smile UTF-8 ASCII). The server-side post-check is the safety net for content that does serialize larger than the estimate. **`ServerProtocolIOTest`** (new) — unit tests for all three protection layers plus a pin on the corrected estimate formula. ## Test plan - [ ] `ServerProtocolIOTest` — 5 new tests covering pre-check, post-check, OOM path, status-only pass-through, and estimate formula - [ ] `PipesMessageTest` — 17 existing wire-protocol tests still pass - [ ] No existing integration test behavior changes (all test documents are well below the DYNAMIC strategy thresholds; UNPACK and CONTENT_ONLY modes bypass the threshold entirely) 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
