Fix a crash that can occur if the sqlite_stat3 or sqlite_stat4 table is corrupt.
FossilOrigin-Name: d51df8a8fcc31c37f6e1c9612204af5738ed865e
This commit is contained in:
parent
af2583c83c
commit
0adbed8a60
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\scrash\sthat\scan\soccur\sfollowing\san\sOOM\sfault.
|
||||
D 2013-08-15T18:43:21.395
|
||||
C Fix\sa\scrash\sthat\scan\soccur\sif\sthe\ssqlite_stat3\sor\ssqlite_stat4\stable\sis\scorrupt.
|
||||
D 2013-08-15T19:56:32.997
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c e60d6329f77e84bac0a300d5227c28a05f5ff5de
|
||||
F src/analyze.c 9533c7e948398bf9628178d6bf9a7845d7e29046
|
||||
F src/attach.c 1816f5a9eea8d2010fc2b22b44f0f63eb3a62704
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
|
||||
@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 83e74db42a49bb185e05f3a44a5d65323aba8a40
|
||||
F test/analyze9.test b73f9514af962a139d2c61d7741b0ba090789ea2
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
@ -1107,7 +1107,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 71070c9fce86103f174220e07771df99b2e01405
|
||||
R fd0e4baaf9a9ffd0fe23644f24c090cf
|
||||
P 9f80b2687012ab7c4d6d654fe19f40878bd78bd8
|
||||
R abb1a9d20998265ab3bcabc4adb13b2c
|
||||
U dan
|
||||
Z 1c4d6e6edcc7281c470c7559e77faff9
|
||||
Z 4cffc531446b09bd876c8b206583a719
|
||||
|
@ -1 +1 @@
|
||||
9f80b2687012ab7c4d6d654fe19f40878bd78bd8
|
||||
d51df8a8fcc31c37f6e1c9612204af5738ed865e
|
@ -1268,6 +1268,44 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
|
||||
/*
|
||||
** Populate the pIdx->aAvgEq[] array based on the samples currently
|
||||
** stored in pIdx->aSample[].
|
||||
*/
|
||||
static void initAvgEq(Index *pIdx){
|
||||
if( pIdx ){
|
||||
IndexSample *aSample = pIdx->aSample;
|
||||
IndexSample *pFinal = &aSample[pIdx->nSample-1];
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pIdx->nColumn; iCol++){
|
||||
int i; /* Used to iterate through samples */
|
||||
tRowcnt sumEq = 0; /* Sum of the nEq values */
|
||||
int nSum = 0; /* Number of terms contributing to sumEq */
|
||||
tRowcnt avgEq = 0;
|
||||
tRowcnt nDLt = pFinal->anDLt[iCol];
|
||||
|
||||
/* Set nSum to the number of distinct (iCol+1) field prefixes that
|
||||
** occur in the stat4 table for this index before pFinal. Set
|
||||
** sumEq to the sum of the nEq values for column iCol for the same
|
||||
** set (adding the value only once where there exist dupicate
|
||||
** prefixes). */
|
||||
for(i=0; i<(pIdx->nSample-1); i++){
|
||||
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
|
||||
sumEq += aSample[i].anEq[iCol];
|
||||
nSum++;
|
||||
}
|
||||
}
|
||||
if( nDLt>nSum ){
|
||||
avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
|
||||
}
|
||||
if( avgEq==0 ) avgEq = 1;
|
||||
pIdx->aAvgEq[iCol] = avgEq;
|
||||
if( pIdx->nSampleCol==1 ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Load the content from either the sqlite_stat4 or sqlite_stat3 table
|
||||
** into the relevant Index.aSample[] arrays.
|
||||
@ -1292,7 +1330,6 @@ static int loadStatTbl(
|
||||
sqlite3_stmt *pStmt = 0; /* An SQL statement being run */
|
||||
char *zSql; /* Text of the SQL statement */
|
||||
Index *pPrevIdx = 0; /* Previous index in the loop */
|
||||
int idx = 0; /* slot in pIdx->aSample[] for next sample */
|
||||
IndexSample *pSample; /* A slot in pIdx->aSample[] */
|
||||
|
||||
assert( db->lookaside.bEnabled==0 );
|
||||
@ -1328,7 +1365,6 @@ static int loadStatTbl(
|
||||
nAvgCol = pIdx->nColumn;
|
||||
}
|
||||
pIdx->nSampleCol = nIdxCol;
|
||||
pIdx->nSample = nSample;
|
||||
nByte = sizeof(IndexSample) * nSample;
|
||||
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
|
||||
nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
|
||||
@ -1340,7 +1376,7 @@ static int loadStatTbl(
|
||||
}
|
||||
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
|
||||
pIdx->aAvgEq = pSpace; pSpace += nAvgCol;
|
||||
for(i=0; i<pIdx->nSample; i++){
|
||||
for(i=0; i<nSample; i++){
|
||||
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
|
||||
pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
|
||||
pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
|
||||
@ -1361,61 +1397,25 @@ static int loadStatTbl(
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
char *zIndex; /* Index name */
|
||||
Index *pIdx; /* Pointer to the index object */
|
||||
int i; /* Loop counter */
|
||||
int nCol = 1; /* Number of columns in index */
|
||||
|
||||
zIndex = (char *)sqlite3_column_text(pStmt, 0);
|
||||
if( zIndex==0 ) continue;
|
||||
pIdx = sqlite3FindIndex(db, zIndex, zDb);
|
||||
if( pIdx==0 ) continue;
|
||||
if( pIdx==pPrevIdx ){
|
||||
idx++;
|
||||
}else{
|
||||
pPrevIdx = pIdx;
|
||||
idx = 0;
|
||||
}
|
||||
assert( idx<pIdx->nSample );
|
||||
/* This next condition is true if data has already been loaded from
|
||||
** the sqlite_stat4 table. In this case ignore stat3 data. */
|
||||
if( bStat3 && pIdx->aSample[idx].anEq[0] ) continue;
|
||||
pSample = &pIdx->aSample[idx];
|
||||
|
||||
if( bStat3==0 ){
|
||||
nCol = pIdx->nColumn+1;
|
||||
nCol = pIdx->nSampleCol;
|
||||
if( bStat3 && nCol>1 ) continue;
|
||||
if( pIdx!=pPrevIdx ){
|
||||
initAvgEq(pPrevIdx);
|
||||
pPrevIdx = pIdx;
|
||||
}
|
||||
pSample = &pIdx->aSample[pIdx->nSample++];
|
||||
decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0);
|
||||
decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0);
|
||||
decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0);
|
||||
|
||||
if( idx==pIdx->nSample-1 ){
|
||||
IndexSample *aSample = pIdx->aSample;
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pIdx->nColumn; iCol++){
|
||||
tRowcnt sumEq = 0; /* Sum of the nEq values */
|
||||
int nSum = 0; /* Number of terms contributing to sumEq */
|
||||
tRowcnt avgEq = 0;
|
||||
tRowcnt nDLt = pSample->anDLt[iCol];
|
||||
|
||||
/* Set nSum to the number of distinct (iCol+1) field prefixes that
|
||||
** occur in the stat4 table for this index before pSample. Set
|
||||
** sumEq to the sum of the nEq values for column iCol for the same
|
||||
** set (adding the value only once where there exist dupicate
|
||||
** prefixes). */
|
||||
for(i=0; i<(pIdx->nSample-1); i++){
|
||||
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
|
||||
sumEq += aSample[i].anEq[iCol];
|
||||
nSum++;
|
||||
}
|
||||
}
|
||||
if( nDLt>nSum ){
|
||||
avgEq = (pSample->anLt[iCol] - sumEq)/(nDLt - nSum);
|
||||
}
|
||||
if( avgEq==0 ) avgEq = 1;
|
||||
pIdx->aAvgEq[iCol] = avgEq;
|
||||
if( bStat3 ) break;
|
||||
}
|
||||
}
|
||||
|
||||
pSample->n = sqlite3_column_bytes(pStmt, 4);
|
||||
pSample->p = sqlite3DbMallocZero(db, pSample->n);
|
||||
if( pSample->p==0 ){
|
||||
@ -1424,6 +1424,7 @@ static int loadStatTbl(
|
||||
}
|
||||
memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
|
||||
}
|
||||
initAvgEq(pPrevIdx);
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
|
@ -290,5 +290,32 @@ do_execsql_test 5.1 {
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# This was also crashing.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE INDEX i2 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4);
|
||||
INSERT INTO t1 VALUES(5, 5);
|
||||
ANALYZE;
|
||||
PRAGMA writable_schema = 1;
|
||||
CREATE TEMP TABLE x1 AS
|
||||
SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat4
|
||||
ORDER BY (rowid%5), rowid;
|
||||
DELETE FROM sqlite_stat4;
|
||||
INSERT INTO sqlite_stat4 SELECT * FROM x1;
|
||||
PRAGMA writable_schema = 0;
|
||||
ANALYZE sqlite_master;
|
||||
}
|
||||
do_execsql_test 6.2 {
|
||||
SELECT * FROM t1 WHERE a = 'abc';
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user