GHSA-wj3v-c3hh-mhqr
CVE Information
Platform
Perl
DBI(Database Interface) — XS core,DBI.xspreparse(). Cross-platform Perl module (CPAN). Affects DBI 1.650 and repo HEAD (1.652); the vulnerable line is long-standing. Exploitable on 32-bit perl builds (ptrsize/ivsize= 4). attachments.zipSummary
preparse()sizes its output buffer withnewSV(strlen(statement) * 7 + 16).strlen()returnssize_tand the multiply is evaluated inSTRLENwidth. On 32-bit perl,STRLENis 32 bits, so a statement ofstrlen ≥ 613,566,757bytes (~585 MB) makesstrlen * 7wrap modulo 2³², producing a tiny allocation.preparse()then copies the full attacker-sized statement into that under-allocated buffer → heap out-of-bounds write of attacker-controlled bytes.Description
DBI.xs(tag 1.650), preparse buffer allocation and the unguarded copy:/* line 4213 */ new_stmt_sv = newSV(strlen(statement) * 7 + 16); /* line 4363 */ *dest++ = *src++; /* copy/emit loop, bound by input length, not reserved size */
strlen(statement)issize_t;strlen * 7is computed inSTRLEN(=size_t). On 32-bit perlsize_tis 32-bit.- For
strlen = 613,566,757:× 7 = 4,294,967,299;mod 2³² = 3;+16 = 19→newSV(19).- The parser writes the input out through the raw
destpointer with no capacity clamp, so it writes ~585 MB into a 19-byte buffer → heap OOB write.- The
idx >= 99999placeholder cap (CVE-2026-14739) does not guard this path — the trigger uses non-placeholder content, which never reaches the cap. The CVE-2026-14739 change from* 6to* 7lowered the wrap threshold (~682.7 MB → ~585.1 MB), marginally widening exposure.- 64-bit perl is not practically affected: the wrap needs
strlen ≥ 2⁶⁴/7 ≈ 2.3 EB.Proof of Concept
32-bit perl (
i686-linux-gnu,ptrsize=4), DBI built from tag 1.650:use strict; use warnings; use DBI; $|=1; my $s = "a" x 613_566_757; # 613566757*7+16 wraps to 19 in 32-bit STRLEN -> newSV(19) my $dbh = DBI->connect("dbi:ExampleP:", "", "", {RaiseError=>0, PrintError=>0}); $dbh->preparse($s, 2, 1); # heap overflow inside preparse()Reproduce end-to-end (native i386 container, no VM, $0):
attachments/build-and-run.sh.Expected Result
preparse()either sizes the buffer correctly or refuses an over-length statement with an error (as it already does for > 99,999 placeholders).Observed Result
Heap buffer overflow inside
preparse(). - Normal build: the ~585 MB source string allocates fine, then the process SIGSEGVs insidepreparse()(autoflush markers confirm the crash is after "calling preparse", not during string allocation). - AddressSanitizer build:heap-buffer-overflow WRITE of size 1 ... #0 preparse DBI.xs:4363 ... 0 bytes to the right of a 21-byte region [Perl_safesysmalloc](21 = wrappednewSV(19)+ allocator rounding).Negative control: the identical harness on 64-bit perl does not overflow —
preparse()returns normally (the size math does not wrap at 64-bit STRLEN). This isolates the 32-bit STRLEN wrap as the load-bearing cause, not the input content or the API call itself. (Independently, adversarial testing showed the placeholder-count path —? x 99998etc. — never exceeds thestrlen*7budget on any bitness, confirming this residual is the integer-wrap, not the CVE-2026-14739 logic.)Impact
Heap out-of-bounds write of attacker-controlled bytes — a memory-corruption primitive. In practice the very large write reaches unmapped memory quickly → reliable crash / denial of service; controlled-corruption / code-execution escalation is not demonstrated and would be constrained by the write extent. Reported honestly as a memory-safety defect, not a demonstrated RCE.
Reachability preconditions (both required): (1) a 32-bit perl build (32-bit Strawberry/ActiveState on Windows, ARM32/embedded appliances, legacy i686 Linux); (2) an application that passes attacker-controlled, unbounded SQL to
DBI::preparse()(e.g.?→:pNplaceholder-normalization middleware) with no input length cap.Callstack
==ERROR: AddressSanitizer: heap-buffer-overflow ... WRITE of size 1 #0 preparse DBI.xs:4363 #1 XS_DBD_____db_preparse DBI.c:5447 #2 XS_DBI_dispatch DBI.xs:3785 #3 Perl_pp_entersub / Perl_runops_standard / perl_run / main 0x...915 is 0 bytes to the right of a 21-byte region allocated by Perl_safesysmalloc SUMMARY: AddressSanitizer: heap-buffer-overflow DBI.xs:4363 in preparseEvidence / Attachments
File What it shows attachments/poc-asan-heap-overflow.txtASAN heap-buffer-overflow WRITE at DBI.xs:4363 in preparse; 21-byte region attachments/poc-normal-build-sigsegv.txtNormal 32-bit build: markers + SIGSEGV localized inside preparse attachments/harness.plMinimal trigger attachments/build-and-run.shEnd-to-end repro in a native i386 container ($0, no VM) attachments/dbi-xs-4213-allocation.txtThe vulnerable allocation line at tag 1.650