/ Check-in [88439a86]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a register allocation bug in the VDBE code generator for PRAGMA integrity_check;
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 88439a866b3b16ad7c308ebe59198662a05e7eeb
User & Date: drh 2016-03-19 00:35:02
References
2017-07-15
19:32 New ticket [a4e06e75] False-positive from "PRAGMA integrity_check". artifact: 1cd21727 user: drh
Context
2016-03-19
14:53
Fix test scripts sqldiff.test and rbudiff.test so that they work with the --testdir option. check-in: 1ffe3cde user: dan tags: trunk
00:40
Fix a VDBE register allocation bug exposed by recent enhancements to PRAGMA integrity_check. check-in: c73b5b9c user: drh tags: apple-osx
00:35
Fix a register allocation bug in the VDBE code generator for PRAGMA integrity_check; check-in: 88439a86 user: drh tags: trunk
2016-03-18
00:39
Fix FTS5 so that it works with SQLITE_OMIT_AUTORESET. check-in: b199637d user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  4247   4247   /*
  4248   4248   ** Mark all temporary registers as being unavailable for reuse.
  4249   4249   */
  4250   4250   void sqlite3ClearTempRegCache(Parse *pParse){
  4251   4251     pParse->nTempReg = 0;
  4252   4252     pParse->nRangeReg = 0;
  4253   4253   }
         4254  +
         4255  +/*
         4256  +** Validate that no temporary register falls within the range of
         4257  +** iFirst..iLast, inclusive.  This routine is only call from within assert()
         4258  +** statements.
         4259  +*/
         4260  +#ifdef SQLITE_DEBUG
         4261  +int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
         4262  +  int i;
         4263  +  if( pParse->nRangeReg>0
         4264  +   && pParse->iRangeReg+pParse->nRangeReg<iLast
         4265  +   && pParse->iRangeReg>=iFirst
         4266  +  ){
         4267  +     return 0;
         4268  +  }
         4269  +  for(i=0; i<pParse->nTempReg; i++){
         4270  +    if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){
         4271  +      return 0;
         4272  +    }
         4273  +  }
         4274  +  return 1;
         4275  +}
         4276  +#endif /* SQLITE_DEBUG */

Changes to src/pragma.c.

  1437   1437   
  1438   1438       /* Do an integrity check on each database file */
  1439   1439       for(i=0; i<db->nDb; i++){
  1440   1440         HashElem *x;
  1441   1441         Hash *pTbls;
  1442   1442         int *aRoot;
  1443   1443         int cnt = 0;
         1444  +      int mxIdx = 0;
         1445  +      int nIdx;
  1444   1446   
  1445   1447         if( OMIT_TEMPDB && i==1 ) continue;
  1446   1448         if( iDb>=0 && i!=iDb ) continue;
  1447   1449   
  1448   1450         sqlite3CodeVerifySchema(pParse, i);
  1449   1451         addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
  1450   1452         VdbeCoverage(v);
................................................................................
  1458   1460         */
  1459   1461         assert( sqlite3SchemaMutexHeld(db, i, 0) );
  1460   1462         pTbls = &db->aDb[i].pSchema->tblHash;
  1461   1463         for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
  1462   1464           Table *pTab = sqliteHashData(x);
  1463   1465           Index *pIdx;
  1464   1466           if( HasRowid(pTab) ) cnt++;
  1465         -        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ cnt++; }
         1467  +        for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
         1468  +        if( nIdx>mxIdx ) mxIdx = nIdx;
  1466   1469         }
  1467   1470         aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
  1468   1471         if( aRoot==0 ) break;
  1469   1472         for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
  1470   1473           Table *pTab = sqliteHashData(x);
  1471   1474           Index *pIdx;
  1472   1475           if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum;
................................................................................
  1473   1476           for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
  1474   1477             aRoot[cnt++] = pIdx->tnum;
  1475   1478           }
  1476   1479         }
  1477   1480         aRoot[cnt] = 0;
  1478   1481   
  1479   1482         /* Make sure sufficient number of registers have been allocated */
  1480         -      pParse->nMem = MAX( pParse->nMem, 14 );
         1483  +      pParse->nMem = MAX( pParse->nMem, 8+mxIdx );
  1481   1484   
  1482   1485         /* Do the b-tree integrity checks */
  1483   1486         sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
  1484   1487         sqlite3VdbeChangeP5(v, (u8)i);
  1485   1488         addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
  1486   1489         sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
  1487   1490            sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
................................................................................
  1510   1513           sqlite3ExprCacheClear(pParse);
  1511   1514           sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
  1512   1515                                      1, 0, &iDataCur, &iIdxCur);
  1513   1516           sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
  1514   1517           for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1515   1518             sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
  1516   1519           }
  1517         -        pParse->nMem = MAX(pParse->nMem, 8+j);
         1520  +        assert( pParse->nMem>=8+j );
         1521  +        assert( sqlite3NoTempsInRange(pParse,1,7+j) );
  1518   1522           sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
  1519   1523           loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
  1520   1524           /* Verify that all NOT NULL columns really are NOT NULL */
  1521   1525           for(j=0; j<pTab->nCol; j++){
  1522   1526             char *zErr;
  1523   1527             int jmp2, jmp3;
  1524   1528             if( j==pTab->iPKey ) continue;

Changes to src/sqliteInt.h.

  3415   3415   int sqlite3RunParser(Parse*, const char*, char **);
  3416   3416   void sqlite3FinishCoding(Parse*);
  3417   3417   int sqlite3GetTempReg(Parse*);
  3418   3418   void sqlite3ReleaseTempReg(Parse*,int);
  3419   3419   int sqlite3GetTempRange(Parse*,int);
  3420   3420   void sqlite3ReleaseTempRange(Parse*,int,int);
  3421   3421   void sqlite3ClearTempRegCache(Parse*);
         3422  +#ifdef SQLITE_DEBUG
         3423  +int sqlite3NoTempsInRange(Parse*,int,int);
         3424  +#endif
  3422   3425   Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
  3423   3426   Expr *sqlite3Expr(sqlite3*,int,const char*);
  3424   3427   void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
  3425   3428   Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
  3426   3429   Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
  3427   3430   Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
  3428   3431   void sqlite3ExprAssignVarNumber(Parse*, Expr*);