]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a crash that can occur if the sqlite_stat3 or sqlite_stat4 table is corrupt.
authordan <dan@noemail.net>
Thu, 15 Aug 2013 19:56:32 +0000 (19:56 +0000)
committerdan <dan@noemail.net>
Thu, 15 Aug 2013 19:56:32 +0000 (19:56 +0000)
FossilOrigin-Name: d51df8a8fcc31c37f6e1c9612204af5738ed865e

manifest
manifest.uuid
src/analyze.c
test/analyze9.test

index a2529d2cb281b46ddc155bada9a81dd3bc0c3129..55b717508b077ff409e6371547ad22efb960affb 100644 (file)
--- a/manifest
+++ b/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
index f0c5e4a7e1ba93e3ca4f40c2eb0071cdeef4f664..3e8d68298e220708354b462734a916534ca06512 100644 (file)
@@ -1 +1 @@
-9f80b2687012ab7c4d6d654fe19f40878bd78bd8
\ No newline at end of file
+d51df8a8fcc31c37f6e1c9612204af5738ed865e
\ No newline at end of file
index 2c7a142fd083aaf8db646708a9f94b328b1f5628..79fd421a785aceacc2f089cbcaba53418b1b9c1d 100644 (file)
@@ -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);
 }
 
index 21b354792b0a7e0f6a1b676e01a6af8cca1fd036..7e67c5f83262bab6b462a2d3c9f8f5ef2e14ed2c 100644 (file)
@@ -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