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]

Reply via email to