ANT-2026-C0BW3XD3 · dlplibs
heap-buffer-overflow high
Severity Claude high · Security research firm high · Maintainer -
Discovered by Claude Opus 4.6
Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.
ANT-2026-C0BW3XD3: Heap-buffer-overflow in MSPUBParser.cpp:1575
When parsing a crafted Microsoft Publisher document, MSPUBParser::getNewFill allocates a 16-byte std::vector at MSPUBParser.cpp:2077 and then reads one byte immediately past its end at line 2084. The bug is reached via MSPUBDocument::parse → parseEscher → parseShapeGroup → parseEscherShape → getNewFill, so any consumer that opens untrusted .pub files (e.g. LibreOffice importers built on libmspub) is exposed. The attacker controls the input document bytes that determine the vector's size and the subsequent index. Impact is likely limited to a crash or a single leaked heap byte.
Target
Project: dlplibs
Location: MSPUBParser.cpp:1575
Technical Details
ASAN: "READ of size 1 at 0x7165cf1e39e0 ... 0 bytes after 16-byte region". The vector created at line 2077 is exactly 16 bytes, but the indexing expression at line 2084 (column 101) accesses element 16, i.e. one past the last valid index. The code appears to lack a bounds check against the vector size before indexing fill color/stop data derived from the Escher shape record.
Crash trace (truncated — full trace in attached crash.log):
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3052835924
INFO: Loaded 1 modules (33587 inline 8-bit counters): 33587 [0x5ca246270a38, 0x5ca246278d6b),
INFO: Loaded 1 PC tables (33587 PCs): 33587 [0x5ca246278d70,0x5ca2462fc0a0),
/out/pubfuzzer: Running 1 inputs 1 time(s) each.
Running: /tmp/poc
EXIT_CODE:1
=== ASAN Report ===
=================================================================
==27==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7165cf1e39e0 at pc 0x5ca24449fac0 bp 0x7ffdccf06550 sp 0x7ffdccf06548
READ of size 1 at 0x7165cf1e39e0 thread T0
#0 0x5ca24449fabf in libmspub::MSPUBParser::getNewFill(std::__1::map<unsigned short, unsigned int, std::__1::less<unsigned short>, std::__1::allocator<std::__1::pair<unsigned short const, unsigned int>>> const&, bool&, std::__1::map<unsigned short, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, std::__1::less<unsigned short>, std::__1::allocator<std::__1::pair<unsigned short const, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>>>>&) /src/libmspub/src/lib/MSPUBParser.cpp:2084:101
#1 0x5ca2444924df in libmspub::MSPUBParser::parseEscherShape(librevenge::RVNGInputStream*, libmspub::EscherContainerInfo const&, libmspub::Coordinate&, libmspub::Coordinate&) /src/libmspub/src/lib/MSPUBParser.cpp:1723:44
#2 0x5ca24448ecd9 in libmspub::MSPUBParser::parseShapeGroup(librevenge::RVNGInputStream*, libmspub::EscherContainerInfo const&, libmspub::Coordinate, libmspub::Coordinate) /src/libmspub/src/lib/MSPUBParser.cpp:1598:7
#3 0x5ca24447e58d in libmspub::MSPUBParser::parseEscher(librevenge::RVNGInputStream*) /src/libmspub/src/lib/MSPUBParser.cpp:1575:7
#4 0x5ca2444772ad in libmspub::MSPUBParser::parse() /src/libmspub/src/lib/MSPUBParser.cpp:219:8
#5 0x5ca2444767b4 in libmspub::MSPUBDocument::parse(librevenge::RVNGInputStream*, librevenge::RVNGDrawingInterface*) /src/libmspub/src/lib/MSPUBDocument.cpp:150:22
#6 0x5ca244475d69 in LLVMFuzzerTestOneInput /src/libmspub/src/fuzz/pubfuzzer.cpp:23:3
#7 0x5ca2446ccc2d in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
[... 27 more frames — full trace in crash.log]
Reproduction
- Craft a .pub document containing an Escher container with a shape whose fill property blob is sized such that the vector constructed at MSPUBParser.cpp:2077 is shorter than the index used at line 2084
- Deliver the file to the victim (email attachment, download, etc.)
- Victim opens/imports the file; parser reaches getNewFill via parseEscher → parseShapeGroup → parseEscherShape
- getNewFill reads one byte past the end of the heap vector
[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-C0BW3XD3.
Reference: ANT-2026-C0BW3XD3
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure
Triage and disclosure were performed by Ada Logics.
- Verdict
- true positive
- Severity
- high
Dates from discovery through public reveal.
- 2026-03-24 Reported to tracker
- 2026-05-19 Sent to maintainer
- 2026-05-25 Patch released
- 2026-06-06 Maintainer acknowledged
- 2026-08-17 Publicly revealed
SHA-3-512 hash:
0fafa89709fdbbb4e17edcd49473be9be669b854ea4d545f7e021f838e7bc877ca5bcc474919cacf4b1c7529fc153a81c4c7f22bfc4fda4b02595633dfa9a7d8
Committed 2026-05-19 15:00 PT
Revealed 2026-08-17 14:14 PT
Verify (download preimage.json)
Show preimage JSON
{
"ant_id": "ANT-2026-C0BW3XD3",
"bug_class": "Heap-buffer-overflow",
"claude_severity": "high",
"commit_sha": null,
"created_at": "2026-03-24T18:27:32+00:00",
"description": "When parsing a crafted Microsoft Publisher document, MSPUBParser::getNewFill allocates a 16-byte std::vector<unsigned char> at MSPUBParser.cpp:2077 and then reads one byte immediately past its end at line 2084. The bug is reached via MSPUBDocument::parse → parseEscher → parseShapeGroup → parseEscherShape → getNewFill, so any consumer that opens untrusted .pub files (e.g. LibreOffice importers built on libmspub) is exposed. The attacker controls the input document bytes that determine the vector's size and the subsequent index. Impact is likely limited to a crash or a single leaked heap byte.",
"discovered_at": null,
"location": "MSPUBParser.cpp:1575",
"poc_sha256": null,
"preimage_version": 1,
"project": "dlplibs",
"reproduction": [
"Craft a .pub document containing an Escher container with a shape whose fill property blob is sized such that the vector constructed at MSPUBParser.cpp:2077 is shorter than the index used at line 2084",
"Deliver the file to the victim (email attachment, download, etc.)",
"Victim opens/imports the file; parser reaches getNewFill via parseEscher → parseShapeGroup → parseEscherShape",
"getNewFill reads one byte past the end of the heap vector"
],
"technical_details": "ASAN: \"READ of size 1 at 0x7165cf1e39e0 ... 0 bytes after 16-byte region\". The vector created at line 2077 is exactly 16 bytes, but the indexing expression at line 2084 (column 101) accesses element 16, i.e. one past the last valid index. The code appears to lack a bounds check against the vector size before indexing fill color/stop data derived from the Escher shape record.",
"title": "Heap-buffer-overflow in MSPUBParser.cpp:1575",
"vendor_severity": "high"
}