Given two sqlite.dll files, one at version 3.45.2, the other at 3.49.2. One vulnerability in the old version is CVE-2025-29088 which has been fixed in 3.49.2. The function that was affected was at 0x180100c70 in version 3.49.2. The corresponding patch is
Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -757,21 +757,26 @@
** Set up the lookaside buffers for a database connection.
** Return SQLITE_OK on success.
** If lookaside is already active, return SQLITE_BUSY.
**
** The sz parameter is the number of bytes in each lookaside slot.
-** The cnt parameter is the number of slots. If pStart is NULL the
-** space for the lookaside memory is obtained from sqlite3_malloc().
-** If pStart is not NULL then it is sz*cnt bytes of memory to use for
-** the lookaside memory.
+** The cnt parameter is the number of slots. If pBuf is NULL the
+** space for the lookaside memory is obtained from sqlite3_malloc()
+** or similar. If pBuf is not NULL then it is sz*cnt bytes of memory
+** to use for the lookaside memory.
*/
-static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
+static int setupLookaside(
+ sqlite3 *db, /* Database connection being configured */
+ void *pBuf, /* Memory to use for lookaside. May be NULL */
+ int sz, /* Desired size of each lookaside memory slot */
+ int cnt /* Number of slots to allocate */
+){
#ifndef SQLITE_OMIT_LOOKASIDE
- void *pStart;
- sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
- int nBig; /* Number of full-size slots */
- int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
+ void *pStart; /* Start of the lookaside buffer */
+ sqlite3_int64 szAlloc; /* Total space set aside for lookaside memory */
+ int nBig; /* Number of full-size slots */
+ int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
if( sqlite3LookasideUsed(db,0)>0 ){
return SQLITE_BUSY;
}
/* Free any existing lookaside buffer for this handle before
@@ -780,33 +785,38 @@
*/
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
/* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
- ** than a pointer to be useful.
+ ** than a pointer and small enough to fit in a u16.
*/
- sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
+ sz = ROUNDDOWN8(sz);
if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
- if( cnt<0 ) cnt = 0;
- if( sz==0 || cnt==0 ){
+ if( sz>65528 ) sz = 65528;
+ /* Count must be at least 1 to be useful, but not so large as to use
+ ** more than 0x7fff0000 total bytes for lookaside. */
+ if( cnt<1 ) cnt = 0;
+ if( sz>0 && cnt>(0x7fff0000/sz) ) cnt = 0x7fff0000/sz;
+ szAlloc = (i64)sz*(i64)cnt;
+ if( szAlloc==0 ){
sz = 0;
pStart = 0;
}else if( pBuf==0 ){
sqlite3BeginBenignMalloc();
- pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */
+ pStart = sqlite3Malloc( szAlloc );
sqlite3EndBenignMalloc();
if( pStart ) szAlloc = sqlite3MallocSize(pStart);
}else{
pStart = pBuf;
}
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( sz>=LOOKASIDE_SMALL*3 ){
nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
- nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL;
}else if( sz>=LOOKASIDE_SMALL*2 ){
nBig = szAlloc/(LOOKASIDE_SMALL+sz);
- nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL;
}else
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( sz>0 ){
nBig = szAlloc/sz;
nSm = 0;
Can you first use get_similar_function to find the corresponding function in version 3.45.2, and then verify if the vulnerability is indeed in version 3.45.2, or has a fix been backported?
I used get_similar_function against the two DLLs and it gave me address 0x18006e5d4 in sqlite3_3.45.2.dll as the counterpart to 0x180100c70 in 3.49.2. I then decompiled both:
• 3.49.2 (at 0x180100c70) includes the new guards introduced by the patch:
– ROUNDDOWN8(sz)
– Bounds on sz (≤ 65528) and cnt (≥ 1 and cnt ≤ 0x7fff0000/sz)
– Uses 64-bit arithmetic for szAlloc, nSm calculations to avoid overflow
• 3.45.2 (at 0x18006e5d4) does not have any of those checks:
– It computes the allocation size as a raw product of the two 32-bit inputs with no overflow check
– No caps on slot size or count
– No two-size lookaside logic or explicit 64-bit safeguards
Conclusion: the old 3.45.2 code is missing the overflow and bounds checks added in the 3.49.2 patch, so the CVE-2025-29088 issue is indeed present in 3.45.2 and was not back-ported.
Can this vulnerability be triggered in version 3.45.2?
Yes – the 3.45.2 build still has the old setupLookaside() with
szAlloc = sz * cnt;
pStart = malloc(szAlloc);
and never bounds-checks or 64-bit-saturates either operand. If you call
sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, NULL /pBuf/, huge_sz, huge_cnt);
with huge_sz and huge_cnt such that sz*cnt overflows a 32-bit multiply, you’ll end up malloc’ing a tiny buffer and then writing way past its end when SQLite builds its free-list. That’s exactly the mis-behavior fixed in 3.49.2, so 3.45.2 is exploitable under the same API.
