ANT-2026-3JR8RVFB · danbloomberg/leptonica

heap-buffer-overflow medium

Severity Claude medium · Security research firm medium · Maintainer -

Discovered by Claude Mythos Preview

REPORT

Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Trail of Bits.

ANT-2026-3JR8RVFB: Heap buffer underwrite via negative size field in sarrayReadStream causing null byte underwrite

sarrayReadStream reads a size field from its input stream without rejecting negative values. The negative size is then used as an offset into a heap-allocated buffer, and a null terminator byte is written at that offset, landing before the start of the allocation. An attacker supplying the serialized sarray data controls the size field and thus the underwrite.

Target

Project: Leptonica
Location: sarrayReadStream()
Discovery: static analysis — not yet dynamically reproduced

Technical Details

The size value read from the stream is not validated to be non-negative before being used to place a terminating null byte, so a negative size yields a write below the buffer's base address (heap buffer underflow).

Reproduction

This finding was identified by static analysis and has not yet been dynamically reproduced. The Technical Details section above describes the code path; a trigger input is not included.

[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]

Acknowledgement

This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-3JR8RVFB.


Reference: ANT-2026-3JR8RVFB
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Trail of Bits.

Verdict
true positive
Severity
medium
UPSTREAM FIX

The change that resolved this finding.

diff --git a/src/pix2.c b/src/pix2.c
index ee03443ff..3bbe34b01 100644
--- a/src/pix2.c
+++ b/src/pix2.c
@@ -1547,6 +1547,14 @@ l_uint32  *datas, *lines;
     if (d != 8 && d != 16 && d != 32)
         return ERROR_INT("depth must be 8, 16 or 32 bpp", __func__, 1);
 
+        /* Clamp border values to image dimensions to prevent
+         * negative index calculations (heap buffer underflow).
+         * When bot > h or right > w, bstart/rstart would go negative. */
+    if (top > h) top = h;
+    if (bot > h) bot = h;
+    if (left > w) left = w;
+    if (right > w) right = w;
+
     datas = pixGetData(pixs);
     wpls = pixGetWpl(pixs);
     if (d == 8) {
diff --git a/src/sarray1.c b/src/sarray1.c
index a2c2d64fb..980e3981d 100644
--- a/src/sarray1.c
+++ b/src/sarray1.c
@@ -1414,7 +1414,8 @@ SARRAY  *sa;
 
     for (i = 0; i < n; i++) {
             /* Get the size of the stored string */
-        if ((fscanf(fp, "%d[%d]:", &index, &size) != 2) || (size > (1 << 30))) {
+        if ((fscanf(fp, "%d[%d]:", &index, &size) != 2) ||
+            (size < 0) || (size > (1 << 30))) {
             success = FALSE;
             L_ERROR("error on string size\n", __func__);
             goto cleanup;

https://github.com/DanBloomberg/leptonica/commit/a0ca522b7d48f471c6225b4a4dc0c63463f10843

TIMELINE

Dates from discovery through public reveal.

  1. 2026-03-20 Sent to maintainer
  2. 2026-03-20 Patch released
  3. 2026-03-29 Reported to tracker
  4. 2026-05-07 Maintainer acknowledged
  5. 2026-08-17 Publicly revealed
PROVENANCE

SHA-3-512 hash:

4f95389e236666b66822f179fbb1d597f1fb0ec7cd01e6183b654b7a64e4d413a8c0e9aaed16719a98f36005a6796d7b94cabc01c9ad599d5ecaf5b9c70d7484

Committed 2026-04-09 11:49 PT

Revealed 2026-08-17 13:03 PT

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-3JR8RVFB",
  "bug_class": "Heap Buffer Underflow",
  "claude_severity": "medium",
  "commit_sha": null,
  "created_at": "2026-03-29T20:43:04+00:00",
  "description": "sarrayReadStream reads a size field from its input stream without rejecting negative values. The negative size is then used as an offset into a heap-allocated buffer, and a null terminator byte is written at that offset, landing before the start of the allocation. An attacker supplying the serialized sarray data controls the size field and thus the underwrite.",
  "discovered_at": null,
  "location": "sarrayReadStream()",
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "Leptonica",
  "reproduction": null,
  "technical_details": "The size value read from the stream is not validated to be non-negative before being used to place a terminating null byte, so a negative size yields a write below the buffer's base address (heap buffer underflow).",
  "title": "Heap buffer underwrite via negative size field in sarrayReadStream causing null byte underwrite",
  "vendor_severity": "medium"
}