ReadTool allocates entire file contents for bounded operations (binary check, text read, base64) #9367

Open
opened 2026-02-16 18:12:17 -05:00 by yindo · 0 comments
Owner

Originally created by @SeanThomasWilliams on GitHub (Feb 14, 2026).

Originally assigned to: @rekram1-node on GitHub.

ReadTool reads entire files into memory in three places even though only a fraction of the content is used. With concurrent agents this causes RSS bloat via mimalloc arena fragmentation.

1. file.text() loads the full file for a 50KB output cap (read.ts:147)

file.text().then(text => text.split("\n")) allocates the entire file as a string + line array. A 500MB file creates a 500MB allocation just to return 50KB. Should stream line-by-line instead.

2. isBinaryFile() reads the full file to check 4KB (read.ts:247-250)

file.arrayBuffer() loads the entire file, then only the first 4096 bytes are inspected. Should use file.slice(0, 4096).arrayBuffer().

3. No size guard on image/PDF base64 encoding (read.ts:117-138)

Buffer.from(await file.bytes()).toString("base64") has no cap. Large images/PDFs create huge byte arrays plus ~1.33x base64 strings. Should reject files above a reasonable threshold.

All three are in a single file and straightforward to fix.

Originally created by @SeanThomasWilliams on GitHub (Feb 14, 2026). Originally assigned to: @rekram1-node on GitHub. ReadTool reads entire files into memory in three places even though only a fraction of the content is used. With concurrent agents this causes RSS bloat via mimalloc arena fragmentation. **1. `file.text()` loads the full file for a 50KB output cap** (`read.ts:147`) `file.text().then(text => text.split("\n"))` allocates the entire file as a string + line array. A 500MB file creates a 500MB allocation just to return 50KB. Should stream line-by-line instead. **2. `isBinaryFile()` reads the full file to check 4KB** (`read.ts:247-250`) `file.arrayBuffer()` loads the entire file, then only the first 4096 bytes are inspected. Should use `file.slice(0, 4096).arrayBuffer()`. **3. No size guard on image/PDF base64 encoding** (`read.ts:117-138`) `Buffer.from(await file.bytes()).toString("base64")` has no cap. Large images/PDFs create huge byte arrays plus ~1.33x base64 strings. Should reject files above a reasonable threshold. All three are in a single file and straightforward to fix.
yindo added the perf label 2026-02-16 18:12:17 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#9367