| https://sqlite.org/src/info/b2ce5ed175cb5029 |
| https://sqlite.org/src/info/6e4a5f22811bcd14 |
| https://sqlite.org/src/info/516ca8945150bdc1 |
| https://sqlite.org/src/info/e1724f1d618cfbcf |
| https://sqlite.org/src/info/c621fc668c6538f9 |
| https://sqlite.org/src/info/c509d8a8aebe0da4 |
| https://sqlite.org/src/info/a9b90aa12eecdd9f |
| |
| --- /sqlite3.c |
| +++ /sqlite3.c |
| @@ -67472,10 +67472,9 @@ |
| rc = newDatabase(pBt); |
| pBt->nPage = get4byte(28 + pBt->pPage1->aData); |
| |
| - /* The database size was written into the offset 28 of the header |
| - ** when the transaction started, so we know that the value at offset |
| - ** 28 is nonzero. */ |
| - assert( pBt->nPage>0 ); |
| + /* pBt->nPage might be zero if the database was corrupt when |
| + ** the transaction was started. Otherwise, it must be at least 1. */ |
| + assert( CORRUPT_DB || pBt->nPage>0 ); |
| } |
| sqlite3BtreeLeave(p); |
| } |
| @@ -70825,6 +70824,7 @@ |
| u16 maskPage = pOld->maskPage; |
| u8 *piCell = aData + pOld->cellOffset; |
| u8 *piEnd; |
| + VVA_ONLY( int nCellAtStart = b.nCell; ) |
| |
| /* Verify that all sibling pages are of the same "type" (table-leaf, |
| ** table-interior, index-leaf, or index-interior). |
| @@ -70853,6 +70853,10 @@ |
| */ |
| memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow)); |
| if( pOld->nOverflow>0 ){ |
| + if( limit<pOld->aiOvfl[0] ){ |
| + rc = SQLITE_CORRUPT_BKPT; |
| + goto balance_cleanup; |
| + } |
| limit = pOld->aiOvfl[0]; |
| for(j=0; j<limit; j++){ |
| b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell)); |
| @@ -70872,6 +70876,7 @@ |
| piCell += 2; |
| b.nCell++; |
| } |
| + assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) ); |
| |
| cntOld[i] = b.nCell; |
| if( i<nOld-1 && !leafData){ |
| @@ -83747,7 +83752,7 @@ |
| ** is clear. Otherwise, if this is an ephemeral cursor created by |
| ** OP_OpenDup, the cursor will not be closed and will still be part |
| ** of a BtShared.pCursor list. */ |
| - p->apCsr[iCur]->isEphemeral = 0; |
| + if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0; |
| sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); |
| p->apCsr[iCur] = 0; |
| } |
| @@ -87258,7 +87263,10 @@ |
| if( pCx ){ |
| /* If the ephermeral table is already open, erase all existing content |
| ** so that the table is empty again, rather than creating a new table. */ |
| - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); |
| + assert( pCx->isEphemeral ); |
| + if( pCx->pBtx ){ |
| + rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); |
| + } |
| }else{ |
| pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); |
| if( pCx==0 ) goto no_mem; |
| @@ -95979,7 +95987,9 @@ |
| #ifndef SQLITE_OMIT_WINDOWFUNC |
| if( pExpr->y.pWin ){ |
| Select *pSel = pNC->pWinSelect; |
| - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); |
| + if( IN_RENAME_OBJECT==0 ){ |
| + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); |
| + } |
| sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); |
| sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); |
| sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); |
| @@ -174132,7 +174142,7 @@ |
| } |
| p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); |
| |
| - if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){ |
| + if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){ |
| return FTS_CORRUPT_VTAB; |
| } |
| blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); |
| @@ -174151,7 +174161,7 @@ |
| } |
| } |
| |
| - assert( p->iOff<=p->nNode ); |
| + assert_fts3_nc( p->iOff<=p->nNode ); |
| return rc; |
| } |
| |
| @@ -204287,7 +204297,11 @@ |
| i64 iOff = *piOff; |
| int iVal; |
| fts5FastGetVarint32(a, i, iVal); |
| - if( iVal==1 ){ |
| + if( iVal<=1 ){ |
| + if( iVal==0 ){ |
| + *pi = i; |
| + return 0; |
| + } |
| fts5FastGetVarint32(a, i, iVal); |
| iOff = ((i64)iVal) << 32; |
| fts5FastGetVarint32(a, i, iVal); |