ANT-2026-QPYFFTMS · osgeo/gdal

stack-buffer-overflow high

Severity Claude critical · Security research firm high (revised; sealed as critical) · Maintainer -

Discovered by Claude Sonnet 4.6

REPORT

Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.

ANT-2026-QPYFFTMS: Stack-buffer-overflow in gdal

Running the reproducer /tmp/poc against aig_fuzzer under libFuzzer produces a non-zero exit (EXIT_CODE:1) but no AddressSanitizer, UBSan, or other sanitizer diagnostic was printed. Without a sanitizer tag, access shape (READ/WRITE), or stack frames, the crash type, faulting function, and source location cannot be determined from this log alone. The only observable signal is that a single crafted input deterministically causes the target to exit abnormally.

Target

Project: osgeo/gdal

Technical Details

The fuzz target aig_fuzzer terminated with EXIT_CODE:1 when executing the provided PoC input, with no sanitizer report or stack trace emitted.

Crash trace:

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 293844668
INFO: Loaded 1 modules   (1021859 inline 8-bit counters): 1021859 [0x5bd227fca460, 0x5bd2280c3c03), 
INFO: Loaded 1 PC tables (1021859 PCs): 1021859 [0x5bd2280c3c08,0x5bd22905b638), 
/out/aig_fuzzer: Running 1 inputs 1 time(s) each.
Running: /tmp/poc
EXIT_CODE:1

Reproduction

Reproduce against the target as described under Technical Details.

[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-QPYFFTMS.


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

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Ada Logics. The severity shown is the firm's current assessment; the report was sealed with the firm's earlier assessment of critical.

Verdict
true positive
Severity
high (revised; sealed as critical)
UPSTREAM FIX

The change that resolved this finding.

diff --git a/frmts/aigrid/aigccitt.c b/frmts/aigrid/aigccitt.c
index a5e983ab7a45..7939d8b615e2 100644
--- a/frmts/aigrid/aigccitt.c
+++ b/frmts/aigrid/aigccitt.c
@@ -4074,7 +4074,7 @@ CPLErr DecompressCCITTRLETile(unsigned char *pabySrcData, int nSrcBytes,
     DecoderState(sp)->runs = NULL;
     DecoderState(sp)->fill = aig_TIFFFax3fillruns;
 
-    if (sizeof(runs_buf) < (size_t)(nBlockXSize * 2 + 3))
+    if (sizeof(runs_buf) / sizeof(GUInt32) < (size_t)(nBlockXSize * 2 + 3))
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Run buffer too small");
         return CE_Failure;
diff --git a/frmts/aigrid/aigopen.c b/frmts/aigrid/aigopen.c
index f61e2b5022a6..06853340ba9a 100644
--- a/frmts/aigrid/aigopen.c
+++ b/frmts/aigrid/aigopen.c
@@ -39,11 +39,12 @@ AIGInfo_t *AIGOpen(const char *pszInputName, const char *pszAccess)
     /*      name.                                                           */
     /* -------------------------------------------------------------------- */
     pszCoverName = CPLStrdup(pszInputName);
-    if (EQUAL(pszCoverName + strlen(pszCoverName) - 4, ".adf"))
+    const size_t nCoverNameLen = strlen(pszCoverName);
+    if (nCoverNameLen > 4 && EQUAL(pszCoverName + nCoverNameLen - 4, ".adf"))
     {
         int i;
 
-        for (i = (int)strlen(pszCoverName) - 1; i > 0; i--)
+        for (i = (int)nCoverNameLen - 1; i > 0; i--)
         {
             if (pszCoverName[i] == '\\' || pszCoverName[i] == '/')
             {

https://github.com/OSGeo/gdal/commit/92ceff5a227dc46a567c53ce8a6c5d477379df9a

TIMELINE

Recorded dates, in order.

  1. 2026-03-24 Discovered or logged
  2. 2026-04-29 Sent to maintainer
  3. 2026-05-08 Patch released
  4. 2026-05-12 Maintainer acknowledged
  5. 2026-07-08 Publicly revealed
PROVENANCE

SHA-3-512 hash:

60f8595cb8a31c15f995648eb10982e6ae90c715f37a827d817b5b2109d57c96de2e3cfd83a5e3fc7c2cd73fb8a5f1e1e9a1912c3358529bff924f34314a6fb7

Committed 2026-05-07 10:18 UTC

Revealed 2026-07-08 23:47 UTC

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-QPYFFTMS",
  "bug_class": "Stack-buffer-overflow",
  "claude_severity": "critical",
  "commit_sha": null,
  "created_at": "2026-03-24T18:28:37+00:00",
  "description": "Running the reproducer /tmp/poc against aig_fuzzer under libFuzzer produces a non-zero exit (EXIT_CODE:1) but no AddressSanitizer, UBSan, or other sanitizer diagnostic was printed. Without a sanitizer tag, access shape (READ/WRITE), or stack frames, the crash type, faulting function, and source location cannot be determined from this log alone. The only observable signal is that a single crafted input deterministically causes the target to exit abnormally.",
  "discovered_at": null,
  "location": null,
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "gdal",
  "reproduction": null,
  "technical_details": null,
  "title": "Stack-buffer-overflow in gdal",
  "vendor_severity": "critical"
}