Improved detection of database corruption while balancing pages from an

auto_vacuum database with overflow pages.  Test cases in TH3.

FossilOrigin-Name: 35f04235c477501390acea126d07a730d81d03cdf7abcd82d861e397b3f75b0f
This commit is contained in:
drh 2019-01-13 20:17:21 +00:00
parent a1bd5c6aae
commit 0f1bf4c1ac
3 changed files with 22 additions and 23 deletions

View File

@ -1,5 +1,5 @@
C Move\sa\slocal\svariable\sdeclaration\sinto\sthe\soutermost\sscope\sin\swhich\sit\nis\sused.\sThis\sfixes\san\sASAN\swarning.
D 2019-01-13T00:58:57.018
C Improved\sdetection\sof\sdatabase\scorruption\swhile\sbalancing\spages\sfrom\san\nauto_vacuum\sdatabase\swith\soverflow\spages.\s\sTest\scases\sin\sTH3.
D 2019-01-13T20:17:21.006
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 45a3fef4d325ac0220c2172aeec4e4321da351f073f3b8e8ddea655f49ef6f2b
@ -453,7 +453,7 @@ F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 789380da841ec283bf75c8b3e2c6423fed63ac16193b247cd43335f07e95f355
F src/btree.c d2ee84255b7372e6a70447f3e260eadfca38d25b1039cf88341df4225cbb3e0e
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
F src/build.c b1e24f1deedee07955cad9c56928cdafa7df1615746688e817bfe0b020a68576
@ -1798,7 +1798,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 0f850a25d67a752fe1e9059c0c3f78e00c222113e556a7605fd3c50817b573cb
R d1042653a3404af381612d805e6f7ade
P ac3b6021d9437ab1c027850d321f0a3e575b008763d8d515e2347f7d4e7c294b
R b3c41bca6e263f72d137d37d5ad93455
U drh
Z c1dc9aa41961f051bb56f64dcc557e3c
Z db68a7c462e1085d4719c3b28e40f5d1

View File

@ -1 +1 @@
ac3b6021d9437ab1c027850d321f0a3e575b008763d8d515e2347f7d4e7c294b
35f04235c477501390acea126d07a730d81d03cdf7abcd82d861e397b3f75b0f

View File

@ -1066,7 +1066,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
#else /* if defined SQLITE_OMIT_AUTOVACUUM */
#define ptrmapPut(w,x,y,z,rc)
#define ptrmapGet(w,x,y,z) SQLITE_OK
#define ptrmapPutOvflPtr(x, y, rc)
#define ptrmapPutOvflPtr(x, y, z, rc)
#endif
/*
@ -1359,18 +1359,20 @@ static u16 cellSize(MemPage *pPage, int iCell){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** If the cell pCell, part of page pPage contains a pointer
** to an overflow page, insert an entry into the pointer-map
** for the overflow page.
** The cell pCell is currently part of page pSrc but will ultimately be part
** of pPage. (pSrc and pPager are often the same.) If pCell contains a
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
Pgno ovfl;
if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
testcase( pSrc!=pPage );
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@ -3491,7 +3493,7 @@ static int setChildPtrmaps(MemPage *pPage){
for(i=0; i<nCell; i++){
u8 *pCell = findCell(pPage, i);
ptrmapPutOvflPtr(pPage, pCell, &rc);
ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);
if( !pPage->leaf ){
Pgno childPgno = get4byte(pCell);
@ -6677,7 +6679,7 @@ static void insertCell(
/* The cell may contain a pointer to an overflow page. If so, write
** the entry for the overflow page into the pointer map.
*/
ptrmapPutOvflPtr(pPage, pCell, pRC);
ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
}
#endif
}
@ -7093,7 +7095,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
if( ISAUTOVACUUM ){
ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
if( szCell>pNew->minLocal ){
ptrmapPutOvflPtr(pNew, pCell, &rc);
ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
}
}
@ -7316,10 +7318,6 @@ static int balance_nonroot(
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
#if 0
TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
#endif
/* At this point pParent may have at most one overflow cell. And if
** this overflow cell is present, it must be the cell with
** index iParentIdx. This scenario comes about when this function
@ -7785,7 +7783,8 @@ static int balance_nonroot(
** populated, not here.
*/
if( ISAUTOVACUUM ){
MemPage *pNew = apNew[0];
MemPage *pOld;
MemPage *pNew = pOld = apNew[0];
u8 *aOld = pNew->aData;
int cntOldNext = pNew->nCell + pNew->nOverflow;
int usableSize = pBt->usableSize;
@ -7795,7 +7794,7 @@ static int balance_nonroot(
for(i=0; i<b.nCell; i++){
u8 *pCell = b.apCell[i];
if( i==cntOldNext ){
MemPage *pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
aOld = pOld->aData;
}
@ -7818,7 +7817,7 @@ static int balance_nonroot(
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
}
if( cachedCellSize(&b,i)>pNew->minLocal ){
ptrmapPutOvflPtr(pNew, pCell, &rc);
ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
}
if( rc ) goto balance_cleanup;
}