SQLite - Integer Overflow in FTS5 Extension
MediumCVE-2025-7709 · Published Aug 15, 2025
### Summary An integer overflow exists in the [FTS5](https://sqlite.org/fts5.html) extension. It occurs when the size of an array of tombstone pointers is calculated and truncated into a 32-bit integer. A pointer to partially controlled data can then be written out of bounds. ### Severity Moderate - The overflow can be triggered by either an attacker who is able to execute arbitrary queries or an attacker that can make an application process a controlled SQLite DB file. ### Proof of Concept ```JavaScript echo "SELECT * FROM articles WHERE articles MATCH 'whatever'" | ./sqlite3 /tmp/poc.sql ================================================================= ==3811642==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5030000012f0 at pc 0x55eafca6599b bp 0x7ffdd1591570 sp 0x7ffdd1591568 READ of size 8 at 0x5030000012f0 thread T0 ``` ### Further Analysis The vulnerability occurs in fts5SegIterAllocTombstone() when nByte is calculated as the total size for an array of pointers: https://github.com/sqlite/sqlite/blob/d2b9cc099d66fe220eb1c4883f865ec94cb37f52/ext/fts5/fts5_index.c#L1952-L1964 ```JavaScript static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter)...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| security-research Product | < 3.50.3 | 3.50.3 |
Details and references
### Summary An integer overflow exists in the [FTS5](https://sqlite.org/fts5.html) extension. It occurs when the size of an array of tombstone pointers is calculated and truncated into a 32-bit integer. A pointer to partially controlled data can then be written out of bounds. ### Severity Moderate - The overflow can be triggered by either an attacker who is able to execute arbitrary queries or an attacker that can make an application process a controlled SQLite DB file. ### Proof of Concept ```JavaScript echo "SELECT * FROM articles WHERE articles MATCH 'whatever'" | ./sqlite3 /tmp/poc.sql ================================================================= ==3811642==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5030000012f0 at pc 0x55eafca6599b bp 0x7ffdd1591570 sp 0x7ffdd1591568 READ of size 8 at 0x5030000012f0 thread T0 ``` ### Further Analysis The vulnerability occurs in fts5SegIterAllocTombstone() when nByte is calculated as the total size for an array of pointers: https://github.com/sqlite/sqlite/blob/d2b9cc099d66fe220eb1c4883f865ec94cb37f52/ext/fts5/fts5_index.c#L1952-L1964 ```JavaScript static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ const int nTomb = pIter->pSeg->nPgTombstone; if( nTomb>0 ){ int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1); Fts5TombstoneArray *pNew; pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ pNew->nTombstone = nTomb; pNew->nRef = 1; pIter->pTombArray = pNew; } } } ``` https://github.com/sqlite/sqlite/blob/d2b9cc099d66fe220eb1c4883f865ec94cb37f52/ext/fts5/fts5_index.c#L566-L568 ```JavaScript /* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */ #define SZ_FTS5TOMBSTONEARRAY(N) \ (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*)) ``` `nByte` is a signed 32-bit integer. While the multiplication done in the `SZ_FTS5TOMBSTONEARRAY` macro is a 64-bit multiplication, the result gets truncated to 32-bit should the resulting value exceed 2^32 - 1. `pIter->pSeg->nPgTombstone` is a fully attacker controlled, 32-bit value that is stored within the metadata tables for a FTS5 table: https://github.com/sqlite/sqlite/blob/837dc09bce7de8971c7488b70cf5da93c60fbed0/ext/fts5/fts5_index.c#L1159 `i += fts5GetVarint32(&pData[i], pSeg->nPgTombstone);` By setting `nPgTombstone` to e.g. 1610612738, `nByte` becomes 32. As a result, only 32 bytes are allocated for an array that is supposed to fit 1610612738 entries. This array is then used in the `fts5MultiIterIsDeleted()` function. An array index is calculated using the `Rowid` of the current context and is bound checked by the number of Tombstone pointers. Since `nTombstone` is the original value that was not overflowed, the `iPg` entry can point out of bounds. If the entry at `iPg` is 0, a structure is allocated and a pointer to it is written out of bounds: https://github.com/sqlite/sqlite/blob/837dc09bce7de8971c7488b70cf5da93c60fbed0/ext/fts5/fts5_index.c#L3302-L3314 ```JavaScript if( pSeg->pLeaf && pArray ){ /* Figure out which page the rowid might be present on. */ int iPg = ((u64)pSeg->iRowid) % pArray->nTombstone; assert( iPg>=0 ); /* If tombstone hash page iPg has not yet been loaded from the ** database, load it now. */ if( pArray->apTombstone[iPg]==0 ){ pArray->apTombstone[iPg] = fts5DataRead(pIter->pIndex, FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg) ); if( pArray->apTombstone[iPg]==0 ) return 0; } ``` Fix can be found here: https://sqlite.org/src/info/63595b74956a9391 ### Timeline **Date reported**: 07/15/2025 **Date fixed**: 07/16/2025 **Date disclosed**: 08/15/2025
- Severity from
- GitHub (reviewed advisory)
More Google advisories
All Google| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Sep 82025 | FFmpeg - Heap-buffer-overflow write in jpeg2000dec | High | No fix yet |
| Sep 82025 | ChatGPT Agent - XSS on file://home/oai/redirect.html | Medium | No fix yet |
| Aug 252025 | SQLite: Integer truncation in findOrCreateAggInfoColumn | High | 3.50.2 |
| Aug 182025 | OpenAI Operator - Click on arbitrary origin by TOCTOU attack | High | No fix yet |
| Aug 142025 | tar-fs Link Directory Traversal Vulnerability | Critical | 3.0.9 |
| Jul 312025 | Python Tar Filter Bypass Vulnerability | High7.5 | No fix yet |