Potentially dangerous negative size term in sqlite3WhereCodeOneLoopStart allocation
(1) By anonymous on 2023-12-19 14:22:52 [source]
Version: 3.44.0
I am chasing a corruption of sqlite data structures. One of the rarer stacktraces that have been captured reads:
#0 sqlite3WhereCodeOneLoopStart (notReady=18446744073709551615, pLevel=<optimized out>, iLevel=0, pWInfo=0x7f14dc0b7370, v=<optimized out>, pParse=0x7f14d2ffd1c0) at sqlite3.c:158072
158072 if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
(gdb) p pTerm
$1 = (WhereTerm *) 0x0
(gdb) bt
#0 sqlite3WhereCodeOneLoopStart (notReady=18446744073709551615, pLevel=<optimized out>, iLevel=0, pWInfo=0x7f14dc0b7370, v=<optimized out>, pParse=0x7f14d2ffd1c0) at sqlite3.c:158072
#1 sqlite3WhereBegin (pParse=pParse@entry=0x7f14d2ffd1c0, pTabList=pTabList@entry=0x7f14dc0c10b0, pWhere=pWhere@entry=0x7f14dc0c1430, pOrderBy=<optimized out>, pResultSet=<optimized out>, pSelect=pSelect@entry=0x7f14dc0c1eb0, wctrlFlags=<optimized out>, iAuxArg=320) at sqlite3.c:35739
#2 0x00007f159994c8f6 in sqlite3Select (pParse=pParse@entry=0x7f14d2ffd1c0, p=<optimized out>, pDest=pDest@entry=0x7f14d2ffc760) at sqlite3.c:149126
#3 0x00007f159997f13f in yy_reduce (yypParser=0x7f14d2ffc7c0, yyLookahead=<optimized out>, pParse=0x7f14d2ffd1c0, yyLookaheadToken=..., yyruleno=84) at sqlite3.c:174205
#4 sqlite3Parser (yyminor=..., yymajor=<optimized out>, yyp=0x7f14d2ffc7c0) at sqlite3.c:44579
#5 sqlite3RunParser (pParse=pParse@entry=0x7f14d2ffd1c0, zSql=<optimized out>, zSql@entry=0x7f1598ddaa50 "SELECT proptag, propval FROM folder_properties WHERE folder_id=? AND proptag=?") at sqlite3.c:45879
#6 0x00007f1599984d29 in sqlite3Prepare (db=db@entry=0x7f14dc0f4a50, zSql=zSql@entry=0x7f1598ddaa50 "SELECT proptag, propval FROM folder_properties WHERE folder_id=? AND proptag=?", nBytes=nBytes@entry=-1, prepFlags=prepFlags@entry=128, pReprepare=pReprepare@entry=0x0, ppStmt=ppStmt@entry=0x7f14d2ffd460, pzTail=0x0) at sqlite3.c:140941
#7 0x00007f159998518f in sqlite3LockAndPrepare (db=0x7f14dc0f4a50, zSql=0x7f1598ddaa50 "SELECT proptag, propval FROM folder_properties WHERE folder_id=? AND proptag=?", nBytes=-1, prepFlags=128, pOld=0x0, ppStmt=0x7f14d2ffd460, pzTail=0x0) at sqlite3.c:141016
#8 0x00007f1599989926 in sqlite3_prepare_v2 (db=db@entry=0x7f14dc0f4a50, zSql=zSql@entry=0x7f1598ddaa50 "SELECT proptag, propval FROM folder_properties WHERE folder_id=? AND proptag=?", nBytes=nBytes@entry=-1, ppStmt=ppStmt@entry=0x7f14d2ffd460, pzTail=pzTail@entry=0x0) at sqlite3.c:141102
Either way, this nullptr seems to originate in pWInfo->sWC.a=0x0
.
So I went reading aimlessy for a bit in source code in the hope of finding something/anything. Have a peek at
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(...)
In this function, one finds:
/* Special case: No FROM clause
*/
if( nTabList==0 ){
This suggests nTabList can be reasonably 0. Now, this function also has this line above the nTabList check:
nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
So if nTabList does happen to be zero, what this spells is
<=> nByteWInfo = ROUND8P(sizeof(WhereInfo) + 18446744073709551504);
<=> nByteWInfo = ROUND8P(856)
<=> nByteWInfo = ROUND8P( offsetof(WhereInfo::a from WhereInfo) )
which means accessing pWInfo->a[0]
is now undefined behavior. While pWInfo->a[0]
shouldn't ideally be accessed under normal circumstances (because nTabList does spell 0), the fact that WhereInfo::a
was declared as WhereLevel a[1];
rather than WhereLevel a[0];
means it is susceptible to a problem of that kind, e.g. if something somewhere did
memset(pWInfo, 0, sizeof(WhereInfo)); or
memcpy(another_winfo, pWInfo, sizeof(*pWInfo));