/ Check-in [8525c30c]
Login

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

Overview
Comment:Improvements to PRAGMA integrity_check for better detection of malformed records. Integrity_check now avoids returning SQLITE_CORRUPT on a corrupt record. Also includes microoptimizations that I stumbled over while working on integrity_check.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 8525c30c1d6676e51b9d9c642450aae3722c129edafdbc39b8435fcfe09b1817
User & Date: drh 2017-09-13 00:33:36
References
2017-09-13
20:20
Test case update due to PRAGMA integrity_check enhancements in [8525c30c]. No changes to code. check-in: 43c6023b user: drh tags: trunk
Context
2017-09-13
12:55
Disable FTS3 matchinfo() tests that assume a littleEndian platform when running on bigEndian. check-in: 87ccdf9c user: drh tags: trunk
00:33
Improvements to PRAGMA integrity_check for better detection of malformed records. Integrity_check now avoids returning SQLITE_CORRUPT on a corrupt record. Also includes microoptimizations that I stumbled over while working on integrity_check. check-in: 8525c30c user: drh tags: trunk
00:13
PRAGMA integrity_check returns SQLITE_OK even if it encounters corruption while scanning indexes. Closed-Leaf check-in: 81f62e99 user: drh tags: improved-integrity-check
00:01
Fix test script comment. No changes to code. check-in: a5a19492 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

   294    294     }
   295    295     return lwr>upr ? 0 : &aPragmaName[mid];
   296    296   }
   297    297   
   298    298   /*
   299    299   ** Helper subroutine for PRAGMA integrity_check:
   300    300   **
   301         -** Generate code to output a single-column result row with the result
   302         -** held in register regResult.  Decrement the result count and halt if
   303         -** the maximum number of result rows have been issued.
          301  +** Generate code to output a single-column result row with a value of the
          302  +** string held in register 3.  Decrement the result count in register 1
          303  +** and halt if the maximum number of result rows have been issued.
   304    304   */
   305         -static int integrityCheckResultRow(Vdbe *v, int regResult){
          305  +static int integrityCheckResultRow(Vdbe *v){
   306    306     int addr;
   307         -  sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
          307  +  sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
   308    308     addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
   309    309     VdbeCoverage(v);
   310         -  sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
          310  +  sqlite3VdbeAddOp0(v, OP_Halt);
   311    311     return addr;
   312    312   }
   313    313   
   314    314   /*
   315    315   ** Process a pragma statement.  
   316    316   **
   317    317   ** Pragmas are of this form:
................................................................................
  1480   1480           mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
  1481   1481         }
  1482   1482       }
  1483   1483       sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
  1484   1484   
  1485   1485       /* Do an integrity check on each database file */
  1486   1486       for(i=0; i<db->nDb; i++){
  1487         -      HashElem *x;
  1488         -      Hash *pTbls;
  1489         -      int *aRoot;
  1490         -      int cnt = 0;
  1491         -      int mxIdx = 0;
  1492         -      int nIdx;
         1487  +      HashElem *x;     /* For looping over tables in the schema */
         1488  +      Hash *pTbls;     /* Set of all tables in the schema */
         1489  +      int *aRoot;      /* Array of root page numbers of all btrees */
         1490  +      int cnt = 0;     /* Number of entries in aRoot[] */
         1491  +      int mxIdx = 0;   /* Maximum number of indexes for any table */
  1493   1492   
  1494   1493         if( OMIT_TEMPDB && i==1 ) continue;
  1495   1494         if( iDb>=0 && i!=iDb ) continue;
  1496   1495   
  1497   1496         sqlite3CodeVerifySchema(pParse, i);
  1498   1497   
  1499   1498         /* Do an integrity check of the B-Tree
................................................................................
  1500   1499         **
  1501   1500         ** Begin by finding the root pages numbers
  1502   1501         ** for all tables and indices in the database.
  1503   1502         */
  1504   1503         assert( sqlite3SchemaMutexHeld(db, i, 0) );
  1505   1504         pTbls = &db->aDb[i].pSchema->tblHash;
  1506   1505         for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
  1507         -        Table *pTab = sqliteHashData(x);
  1508         -        Index *pIdx;
         1506  +        Table *pTab = sqliteHashData(x);  /* Current table */
         1507  +        Index *pIdx;                      /* An index on pTab */
         1508  +        int nIdx;                         /* Number of indexes on pTab */
  1509   1509           if( HasRowid(pTab) ) cnt++;
  1510   1510           for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
  1511   1511           if( nIdx>mxIdx ) mxIdx = nIdx;
  1512   1512         }
  1513   1513         aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
  1514   1514         if( aRoot==0 ) break;
  1515   1515         for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
................................................................................
  1529   1529         /* Do the b-tree integrity checks */
  1530   1530         sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
  1531   1531         sqlite3VdbeChangeP5(v, (u8)i);
  1532   1532         addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
  1533   1533         sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
  1534   1534            sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
  1535   1535            P4_DYNAMIC);
  1536         -      sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
  1537         -      sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
  1538         -      integrityCheckResultRow(v, 2);
         1536  +      sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
         1537  +      integrityCheckResultRow(v);
  1539   1538         sqlite3VdbeJumpHere(v, addr);
  1540   1539   
  1541   1540         /* Make sure all the indices are constructed correctly.
  1542   1541         */
  1543   1542         for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
  1544   1543           Table *pTab = sqliteHashData(x);
  1545   1544           Index *pIdx, *pPk;
  1546   1545           Index *pPrior = 0;
  1547   1546           int loopTop;
  1548   1547           int iDataCur, iIdxCur;
  1549   1548           int r1 = -1;
  1550   1549   
  1551   1550           if( pTab->tnum<1 ) continue;  /* Skip VIEWs or VIRTUAL TABLEs */
  1552         -        if( pTab->pCheck==0
  1553         -         && (pTab->tabFlags & TF_HasNotNull)==0
  1554         -         && (pTab->pIndex==0 || isQuick)
  1555         -        ){
  1556         -          continue;  /* No additional checks needed for this table */
  1557         -        }
  1558   1551           pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
  1559   1552           sqlite3ExprCacheClear(pParse);
  1560   1553           sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
  1561   1554                                      1, 0, &iDataCur, &iIdxCur);
         1555  +        /* reg[7] counts the number of entries in the table.
         1556  +        ** reg[8+i] counts the number of entries in the i-th index 
         1557  +        */
  1562   1558           sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
  1563   1559           for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1564   1560             sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
  1565   1561           }
  1566   1562           assert( pParse->nMem>=8+j );
  1567   1563           assert( sqlite3NoTempsInRange(pParse,1,7+j) );
  1568   1564           sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
................................................................................
  1575   1571             if( pTab->aCol[j].notNull==0 ) continue;
  1576   1572             sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
  1577   1573             sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
  1578   1574             jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
  1579   1575             zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
  1580   1576                                 pTab->aCol[j].zName);
  1581   1577             sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
  1582         -          integrityCheckResultRow(v, 3);
         1578  +          integrityCheckResultRow(v);
  1583   1579             sqlite3VdbeJumpHere(v, jmp2);
  1584   1580           }
  1585   1581           /* Verify CHECK constraints */
  1586         -        sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
  1587   1582           if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
  1588   1583             ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
  1589   1584             if( db->mallocFailed==0 ){
  1590   1585               int addrCkFault = sqlite3VdbeMakeLabel(v);
  1591   1586               int addrCkOk = sqlite3VdbeMakeLabel(v);
  1592   1587               char *zErr;
  1593   1588               int k;
................................................................................
  1599   1594               sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, 
  1600   1595                   SQLITE_JUMPIFNULL);
  1601   1596               sqlite3VdbeResolveLabel(v, addrCkFault);
  1602   1597               pParse->iSelfTab = 0;
  1603   1598               zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
  1604   1599                   pTab->zName);
  1605   1600               sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
  1606         -            integrityCheckResultRow(v, 3);
         1601  +            integrityCheckResultRow(v);
  1607   1602               sqlite3VdbeResolveLabel(v, addrCkOk);
  1608   1603               sqlite3ExprCachePop(pParse);
  1609   1604             }
  1610   1605             sqlite3ExprListDelete(db, pCheck);
  1611   1606           }
  1612         -        /* Validate index entries for the current row */
  1613         -        for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
  1614         -          int jmp2, jmp3, jmp4, jmp5;
  1615         -          int ckUniq = sqlite3VdbeMakeLabel(v);
  1616         -          if( pPk==pIdx ) continue;
  1617         -          r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
  1618         -                                       pPrior, r1);
  1619         -          pPrior = pIdx;
  1620         -          sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);  /* increment entry count */
  1621         -          /* Verify that an index entry exists for the current table row */
  1622         -          jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
  1623         -                                      pIdx->nColumn); VdbeCoverage(v);
  1624         -          sqlite3VdbeLoadString(v, 3, "row ");
  1625         -          sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
  1626         -          sqlite3VdbeLoadString(v, 4, " missing from index ");
  1627         -          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
  1628         -          jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
  1629         -          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
  1630         -          jmp4 = integrityCheckResultRow(v, 3);
  1631         -          sqlite3VdbeJumpHere(v, jmp2);
  1632         -          /* For UNIQUE indexes, verify that only one entry exists with the
  1633         -          ** current key.  The entry is unique if (1) any column is NULL
  1634         -          ** or (2) the next entry has a different key */
  1635         -          if( IsUniqueIndex(pIdx) ){
  1636         -            int uniqOk = sqlite3VdbeMakeLabel(v);
  1637         -            int jmp6;
  1638         -            int kk;
  1639         -            for(kk=0; kk<pIdx->nKeyCol; kk++){
  1640         -              int iCol = pIdx->aiColumn[kk];
  1641         -              assert( iCol!=XN_ROWID && iCol<pTab->nCol );
  1642         -              if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
  1643         -              sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
  1644         -              VdbeCoverage(v);
         1607  +        if( !isQuick ){ /* Omit the remaining tests for quick_check */
         1608  +          /* Sanity check on record header decoding */
         1609  +          sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
         1610  +          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
         1611  +          /* Validate index entries for the current row */
         1612  +          for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
         1613  +            int jmp2, jmp3, jmp4, jmp5;
         1614  +            int ckUniq = sqlite3VdbeMakeLabel(v);
         1615  +            if( pPk==pIdx ) continue;
         1616  +            r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
         1617  +                                         pPrior, r1);
         1618  +            pPrior = pIdx;
         1619  +            sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
         1620  +            /* Verify that an index entry exists for the current table row */
         1621  +            jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
         1622  +                                        pIdx->nColumn); VdbeCoverage(v);
         1623  +            sqlite3VdbeLoadString(v, 3, "row ");
         1624  +            sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
         1625  +            sqlite3VdbeLoadString(v, 4, " missing from index ");
         1626  +            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
         1627  +            jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
         1628  +            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
         1629  +            jmp4 = integrityCheckResultRow(v);
         1630  +            sqlite3VdbeJumpHere(v, jmp2);
         1631  +            /* For UNIQUE indexes, verify that only one entry exists with the
         1632  +            ** current key.  The entry is unique if (1) any column is NULL
         1633  +            ** or (2) the next entry has a different key */
         1634  +            if( IsUniqueIndex(pIdx) ){
         1635  +              int uniqOk = sqlite3VdbeMakeLabel(v);
         1636  +              int jmp6;
         1637  +              int kk;
         1638  +              for(kk=0; kk<pIdx->nKeyCol; kk++){
         1639  +                int iCol = pIdx->aiColumn[kk];
         1640  +                assert( iCol!=XN_ROWID && iCol<pTab->nCol );
         1641  +                if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
         1642  +                sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
         1643  +                VdbeCoverage(v);
         1644  +              }
         1645  +              jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
         1646  +              sqlite3VdbeGoto(v, uniqOk);
         1647  +              sqlite3VdbeJumpHere(v, jmp6);
         1648  +              sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
         1649  +                                   pIdx->nKeyCol); VdbeCoverage(v);
         1650  +              sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
         1651  +              sqlite3VdbeGoto(v, jmp5);
         1652  +              sqlite3VdbeResolveLabel(v, uniqOk);
  1645   1653               }
  1646         -            jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
  1647         -            sqlite3VdbeGoto(v, uniqOk);
  1648         -            sqlite3VdbeJumpHere(v, jmp6);
  1649         -            sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
  1650         -                                 pIdx->nKeyCol); VdbeCoverage(v);
  1651         -            sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
  1652         -            sqlite3VdbeGoto(v, jmp5);
  1653         -            sqlite3VdbeResolveLabel(v, uniqOk);
         1654  +            sqlite3VdbeJumpHere(v, jmp4);
         1655  +            sqlite3ResolvePartIdxLabel(pParse, jmp3);
  1654   1656             }
  1655         -          sqlite3VdbeJumpHere(v, jmp4);
  1656         -          sqlite3ResolvePartIdxLabel(pParse, jmp3);
  1657   1657           }
  1658   1658           sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
  1659   1659           sqlite3VdbeJumpHere(v, loopTop-1);
  1660   1660   #ifndef SQLITE_OMIT_BTREECOUNT
  1661   1661           if( !isQuick ){
  1662   1662             sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
  1663   1663             for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1664   1664               if( pPk==pIdx ) continue;
  1665   1665               sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
  1666   1666               addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
  1667   1667               sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
  1668         -            sqlite3VdbeLoadString(v, 3, pIdx->zName);
  1669         -            sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
  1670         -            integrityCheckResultRow(v, 7);
         1668  +            sqlite3VdbeLoadString(v, 4, pIdx->zName);
         1669  +            sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
         1670  +            integrityCheckResultRow(v);
  1671   1671               sqlite3VdbeJumpHere(v, addr);
  1672   1672             }
  1673   1673           }
  1674   1674   #endif /* SQLITE_OMIT_BTREECOUNT */
  1675   1675         } 
  1676   1676       }
  1677   1677       {
  1678   1678         static const int iLn = VDBE_OFFSET_LINENO(2);
  1679   1679         static const VdbeOpList endCode[] = {
  1680   1680           { OP_AddImm,      1, 0,        0},    /* 0 */
  1681   1681           { OP_IfNotZero,   1, 4,        0},    /* 1 */
  1682   1682           { OP_String8,     0, 3,        0},    /* 2 */
  1683   1683           { OP_ResultRow,   3, 1,        0},    /* 3 */
         1684  +        { OP_Halt,        0, 0,        0},    /* 4 */
         1685  +        { OP_String8,     0, 3,        0},    /* 5 */
         1686  +        { OP_Goto,        0, 3,        0},    /* 6 */
  1684   1687         };
  1685   1688         VdbeOp *aOp;
  1686   1689   
  1687   1690         aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
  1688   1691         if( aOp ){
  1689   1692           aOp[0].p2 = 1-mxErr;
  1690   1693           aOp[2].p4type = P4_STATIC;
  1691   1694           aOp[2].p4.z = "ok";
         1695  +        aOp[5].p4type = P4_STATIC;
         1696  +        aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
  1692   1697         }
         1698  +      sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
  1693   1699       }
  1694   1700     }
  1695   1701     break;
  1696   1702   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  1697   1703   
  1698   1704   #ifndef SQLITE_OMIT_UTF16
  1699   1705     /*

Changes to src/vdbe.c.

  2457   2457         ** Type entries can be between 1 and 5 bytes each.  But 4 and 5 byte
  2458   2458         ** types use so much data space that there can only be 4096 and 32 of
  2459   2459         ** them, respectively.  So the maximum header length results from a
  2460   2460         ** 3-byte type for each of the maximum of 32768 columns plus three
  2461   2461         ** extra bytes for the header length itself.  32768*3 + 3 = 98307.
  2462   2462         */
  2463   2463         if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
  2464         -        rc = SQLITE_CORRUPT_BKPT;
  2465         -        goto abort_due_to_error;
         2464  +        goto op_column_corrupt;
  2466   2465         }
  2467   2466       }else{
  2468   2467         /* This is an optimization.  By skipping over the first few tests
  2469   2468         ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
  2470   2469         ** measurable performance gain.
  2471   2470         **
  2472   2471         ** This branch is taken even if aOffset[0]==0.  Such a record is never
................................................................................
  2531   2530          || (offset64 > pC->payloadSize)
  2532   2531         ){
  2533   2532           if( aOffset[0]==0 ){
  2534   2533             i = 0;
  2535   2534             zHdr = zEndHdr;
  2536   2535           }else{
  2537   2536             if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
  2538         -          rc = SQLITE_CORRUPT_BKPT;
  2539         -          goto abort_due_to_error;
         2537  +          goto op_column_corrupt;
  2540   2538           }
  2541   2539         }
  2542   2540   
  2543   2541         pC->nHdrParsed = i;
  2544   2542         pC->iHdrOffset = (u32)(zHdr - zData);
  2545   2543         if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
  2546   2544       }else{
................................................................................
  2627   2625       }
  2628   2626     }
  2629   2627   
  2630   2628   op_column_out:
  2631   2629     UPDATE_MAX_BLOBSIZE(pDest);
  2632   2630     REGISTER_TRACE(pOp->p3, pDest);
  2633   2631     break;
         2632  +
         2633  +op_column_corrupt:
         2634  +  if( aOp[0].p3>0 ){
         2635  +    pOp = &aOp[aOp[0].p3-1];
         2636  +    break;
         2637  +  }else{
         2638  +    rc = SQLITE_CORRUPT_BKPT;
         2639  +    goto abort_due_to_error;
         2640  +  }
  2634   2641   }
  2635   2642   
  2636   2643   /* Opcode: Affinity P1 P2 * P4 *
  2637   2644   ** Synopsis: affinity(r[P1@P2])
  2638   2645   **
  2639   2646   ** Apply affinities to a range of P2 registers starting with P1.
  2640   2647   **
................................................................................
  7011   7018   
  7012   7019     REGISTER_TRACE(pOp->p3, pOut);
  7013   7020     UPDATE_MAX_BLOBSIZE(pOut);
  7014   7021     break;
  7015   7022   }
  7016   7023   
  7017   7024   
  7018         -/* Opcode: Init P1 P2 * P4 *
         7025  +/* Opcode: Init P1 P2 P3 P4 *
  7019   7026   ** Synopsis: Start at P2
  7020   7027   **
  7021   7028   ** Programs contain a single instance of this opcode as the very first
  7022   7029   ** opcode.
  7023   7030   **
  7024   7031   ** If tracing is enabled (by the sqlite3_trace()) interface, then
  7025   7032   ** the UTF-8 string contained in P4 is emitted on the trace callback.
  7026   7033   ** Or if P4 is blank, use the string returned by sqlite3_sql().
  7027   7034   **
  7028   7035   ** If P2 is not zero, jump to instruction P2.
  7029   7036   **
  7030   7037   ** Increment the value of P1 so that OP_Once opcodes will jump the
  7031   7038   ** first time they are evaluated for this run.
         7039  +**
         7040  +** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
         7041  +** error is encountered.
  7032   7042   */
  7033   7043   case OP_Init: {          /* jump */
  7034   7044     char *zTrace;
  7035   7045     int i;
  7036   7046   
  7037   7047     /* If the P4 argument is not NULL, then it must be an SQL comment string.
  7038   7048     ** The "--" string is broken up to prevent false-positives with srcck1.c.

Changes to src/vdbeaux.c.

  2154   2154     }
  2155   2155   
  2156   2156     /* Delete any auxdata allocations made by the VM */
  2157   2157     if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0);
  2158   2158     assert( p->pAuxData==0 );
  2159   2159   }
  2160   2160   
  2161         -/*
  2162         -** Clean up the VM after a single run.
  2163         -*/
  2164         -static void Cleanup(Vdbe *p){
  2165         -  sqlite3 *db = p->db;
  2166         -
  2167         -#ifdef SQLITE_DEBUG
  2168         -  /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  2169         -  ** Vdbe.aMem[] arrays have already been cleaned up.  */
  2170         -  int i;
  2171         -  if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
  2172         -  if( p->aMem ){
  2173         -    for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
  2174         -  }
  2175         -#endif
  2176         -
  2177         -  sqlite3DbFree(db, p->zErrMsg);
  2178         -  p->zErrMsg = 0;
  2179         -  p->pResultSet = 0;
  2180         -}
  2181         -
  2182   2161   /*
  2183   2162   ** Set the number of result columns that will be returned by this SQL
  2184   2163   ** statement. This is now set at compile time, rather than during
  2185   2164   ** execution of the vdbe program so that sqlite3_column_count() can
  2186   2165   ** be called on an SQL statement before sqlite3_step().
  2187   2166   */
  2188   2167   void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
................................................................................
  2900   2879     ** and error message from the VDBE into the main database structure.  But
  2901   2880     ** if the VDBE has just been set to run but has not actually executed any
  2902   2881     ** instructions yet, leave the main database error information unchanged.
  2903   2882     */
  2904   2883     if( p->pc>=0 ){
  2905   2884       vdbeInvokeSqllog(p);
  2906   2885       sqlite3VdbeTransferError(p);
  2907         -    sqlite3DbFree(db, p->zErrMsg);
  2908         -    p->zErrMsg = 0;
  2909   2886       if( p->runOnlyOnce ) p->expired = 1;
  2910   2887     }else if( p->rc && p->expired ){
  2911   2888       /* The expired flag was set on the VDBE before the first call
  2912   2889       ** to sqlite3_step(). For consistency (since sqlite3_step() was
  2913   2890       ** called), set the database error in this case as well.
  2914   2891       */
  2915   2892       sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
  2916         -    sqlite3DbFree(db, p->zErrMsg);
  2917         -    p->zErrMsg = 0;
  2918   2893     }
  2919   2894   
  2920         -  /* Reclaim all memory used by the VDBE
         2895  +  /* Reset register contents and reclaim error message memory.
  2921   2896     */
  2922         -  Cleanup(p);
         2897  +#ifdef SQLITE_DEBUG
         2898  +  /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
         2899  +  ** Vdbe.aMem[] arrays have already been cleaned up.  */
         2900  +  int i;
         2901  +  if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
         2902  +  if( p->aMem ){
         2903  +    for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
         2904  +  }
         2905  +#endif
         2906  +  sqlite3DbFree(db, p->zErrMsg);
         2907  +  p->zErrMsg = 0;
         2908  +  p->pResultSet = 0;
  2923   2909   
  2924   2910     /* Save profiling information from this VDBE run.
  2925   2911     */
  2926   2912   #ifdef VDBE_PROFILE
  2927   2913     {
  2928   2914       FILE *out = fopen("vdbe_profile.out", "a");
  2929   2915       if( out ){

Changes to test/pragma.test.

  1949   1949   
  1950   1950   sqlite3 db test.db
  1951   1951   do_catchsql_test 24.1 {
  1952   1952     SELECT * FROM t1;
  1953   1953   } {1 {database disk image is malformed}}
  1954   1954   do_catchsql_test 24.2 {
  1955   1955     PRAGMA integrity_check;
  1956         -} {1 {database disk image is malformed}}
         1956  +} {0 {{database disk image is malformed}}}
  1957   1957   
  1958   1958   database_never_corrupt
  1959   1959   finish_test