Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-39113 — Advisory and AddressSanitizer reproducer for a SQLite SQLAR heap-buffer-overflow triggered by a crafted SZ value causing truncated allocation and zlib out-of-bounds write. | Kitploit
Tools/GitHubGitHub/20000419/cve-2026-39113
Vulnerability AnalysisCode AnalysisExploitationDatabase SecurityBinary Exploitation
GitHub20000419/cve-2026-39113

CVE-2026-39113

Advisory and AddressSanitizer reproducer for a SQLite SQLAR heap-buffer-overflow triggered by a crafted SZ value causing truncated allocation and zlib out-of-bounds write.

View Repository
1 day agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-39113: Heap Buffer Overflow in SQLite's Optional SQLAR Extension

Executive Summary

CVE-2026-39113 is a heap buffer overflow in SQLite's optional SQLAR extension. In an application that has loaded the extension, an attacker who can invoke sqlar_uncompress() with a controlled compressed blob and size can cause zlib to write beyond a heap allocation on an LP64 system. This is a memory-safety boundary failure inside the host process; it is not a SQLite database-file parsing issue, an authentication bypass, or a flaw reachable in every default SQLite deployment.

The vulnerable behavior was introduced on 2026-03-11 by Git commit 169f68e (Fossil check-in 8bdc0d485e3ad0c7...) and corrected on 2026-04-01 by Git commit 34e139d (Fossil check-in 6194f3b5314ef98b...). The affected scope is source snapshots and custom builds from 169f68e through the parent of 34e139d. No official SQLite release was verified vulnerable: SQLite 3.52.0 predates the introduction, and SQLite 3.53.0 contains both the introducing change and the fix. SQLite 3.53.0 is therefore the first official release containing the corrected code, not an affected release.

I reviewed the exact vulnerable revision, the introducing and fixing changes, and the 3.52.0 and 3.53.0 release snapshots. I also inspected the preserved output from an authorised run in a disposable WSL2 Ubuntu 24.04 environment. AddressSanitizer observed a heap-buffer-overflow followed by process termination, establishing native heap corruption and denial of service. Code execution was not demonstrated.

Background

SQLAR is an SQLite archive format. The optional extension in ext/misc/sqlar.c registers sqlar_compress() and sqlar_uncompress() as SQL functions. It is not part of every application using SQLite; the vulnerable path requires the extension to be present and loaded.

For this report, Mallory controls the blob and SZ arguments supplied to:

root@kitploit:~
SELECT sqlar_uncompress(?1, ?2);

The tested environment had a 32-bit int and 64-bit sqlite3_int64 and zlib uLongf. The function should allocate at least as much memory as zlib is permitted to write. Instead, the vulnerable source converts the 64-bit size to the 32-bit parameter type of sqlite3_malloc() while retaining the full value for uncompress().

The vulnerable source snapshot printed Configuring SQLite version 3.53.0 during configuration. That development-version string must not be confused with the official SQLite 3.53.0 release dated 2026-04-09, whose source contains the fix.

Vulnerability Details

At the assessed revision, sqlarUncompressFunc() in ext/misc/sqlar.c reads the attacker-controlled size as a 64-bit integer:

root@kitploit:~
sqlite3_int64 sz;

sz = sqlite3_value_int64(argv[1]);

If sz is positive and differs from the input blob length, the same value is used in two incompatible ways:

root@kitploit:~
uLongf szf = sz;
const Bytef *pData = sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);

if( pOut==0 ){
  sqlite3_result_error_nomem(context);
}else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
  sqlite3_result_error(context, "error in uncompress()", -1);
}

At this revision, SQLite declares sqlite3_malloc(int). On the tested LP64 build, the PoC value 4294967328 (0x100000020) became 32 when passed to that API, while szf retained the full 64-bit value. SQLite therefore made a small allocation, but zlib was told that the output buffer could hold more than 4 GiB. Decompressing a 42-byte blob representing 4096 bytes of data then crossed the allocation boundary.

The mismatch entered the project when the 2026-03-11 change replaced sqlite3_value_int() with sqlite3_value_int64() without changing the allocation API. Source review of SQLite 3.52.0 shows the earlier 32-bit read, so the full-width/short-allocation mismatch was not present there. The 2026-04-01 fix changed the allocation to sqlite3_malloc64(sz). Source review of the official 3.53.0 tag confirms that corrected call.

Exploitability Analysis

The demonstrated primitive is an out-of-bounds heap write in the process hosting SQLite. The preserved run shows AddressSanitizer detecting the first invalid one-byte write immediately after a 40-byte heap region allocated through sqlite3_malloc(), followed by an abort. This directly supports process crash and denial of service.

Exploitation requires all of the following:

  • the optional SQLAR extension is loaded;
  • Mallory can invoke sqlar_uncompress() with a controlled blob and SZ value;
  • int is 32 bits while sqlite3_int64 and zlib uLongf are 64 bits; and
  • the narrowed allocation succeeds, allowing zlib to begin decompression.

The PoC controls the decompressed bytes, which is relevant to the severity of native heap corruption. However, turning this primitive into code execution would depend on allocator layout, surrounding process state, mitigations, and a suitable application-level route. No such chain was tested or demonstrated, so this report does not claim code execution.

The preserved run did not include a runtime negative control against the fixed revision. Two source-level controls narrow the explanation: SQLite 3.52.0 reads the size with the 32-bit API, and the official 3.53.0 source allocates with sqlite3_malloc64(). These checks support the identified introduction and fix but are not presented as executed fixed-target tests. The prevalence of applications loading this optional extension is unknown.

Proof of Concept

The repository includes:

  • poc/verify_sqlar_poc.c, which creates a 4096-byte payload, compresses it, loads sqlar.so, and binds SZ = 4294967328;
  • poc/reproduce.sh, which clones pinned SQLite and zlib revisions, builds them with AddressSanitizer, compiles the extension and harness, and runs the trigger; and
  • evidence/asan-summary.txt, a path-normalized summary of the observed authorised run.

Run the reproducer only in a disposable Linux or WSL environment. It intentionally triggers memory corruption and an AddressSanitizer abort. The script requires git, make, a C compiler, standard build tools, and network access:

root@kitploit:~
chmod +x poc/reproduce.sh
./poc/reproduce.sh

The reproducer was run again on 2026-08-21 on Ubuntu 24.04 under WSL2 and produced the same AddressSanitizer finding. Its relevant output was:

root@kitploit:~
env: sizeof(int)=4 sizeof(sqlite3_int64)=8 sizeof(uLongf)=8
payload: plain=4096 compressed=42 evil_sz=4294967328 low32=32

ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
    #0 inflate_fast zlib/inffast.c:252
    #4 uncompress zlib/uncompr.c:100
    #5 sqlarUncompressFunc sqlite/ext/misc/sqlar.c:97

The write occurred immediately after a 40-byte heap region.
SUMMARY: AddressSanitizer: heap-buffer-overflow in inflate_fast
ABORTING
PoC exit status: 1

This output shows the incompatible type widths and crafted size, the zlib write, the call from sqlarUncompressFunc(), and the allocation boundary violation. The reproduction script deletes its temporary build directory on exit unless KEEP_BUILD=1 is set.

Remediation

Upstream corrected the vulnerable allocation in commit 34e139d:

root@kitploit:~
-    Bytef *pOut = sqlite3_malloc(sz);
+    Bytef *pOut = sqlite3_malloc64(sz);

This keeps the allocation width consistent with the positive 64-bit sz value retained in uLongf szf and passed to zlib. The corrected code is present in official SQLite 3.53.0. Users of source snapshots or custom builds containing the vulnerable interval should update to 34e139d or later. Applications that do not require SQLAR should avoid loading the extension, and applications that do use it should prevent untrusted callers from supplying arbitrary arguments to sqlar_uncompress().

A focused regression test should exercise the SQL function with a valid compressed blob and an SZ value above INT_MAX whose low 32 bits are small. It should verify that the fixed build does not perform a truncated allocation and should retain ordinary successful decompression and invalid-input error cases as controls.

Summary

CVE-2026-39113 affects only SQLite source snapshots and custom builds from 169f68e through the parent of 34e139d when the optional SQLAR extension is loaded and attacker-controlled calls reach sqlar_uncompress() on an LP64 build. A 64-bit size was narrowed by sqlite3_malloc(int) while zlib retained the full value, producing an AddressSanitizer-confirmed heap-buffer-overflow and process abort. No official SQLite release was verified vulnerable, and code execution was not demonstrated. The upstream change to sqlite3_malloc64(sz) is present in official SQLite 3.53.0 and removes the allocation-width mismatch.

Download Tool