/ Check-in [8844e8bf]
Login

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

Overview
Comment:Add extended return code SQLITE_CORRUPT_VTAB. Returned when the tcontents of the sqlite tables used internally by a virtual table module are invalid or inconsistent.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8844e8bfb87314fb40ecb92705e8fff88f72bb38
User & Date: dan 2011-05-17 15:56:16
Context
2011-05-17
18:53
Add the sqlite3_uri_parameter() interface function for use in building new VFSes. check-in: 6b5de95f user: drh tags: trunk
15:56
Add extended return code SQLITE_CORRUPT_VTAB. Returned when the tcontents of the sqlite tables used internally by a virtual table module are invalid or inconsistent. check-in: 8844e8bf user: dan tags: trunk
15:21
Avoid exceeding array bounds when reading a corrupt database file in autovacuum mode. Fixes a problem discovered by John Regehr and Peng Li using a customized clang compiler. check-in: f7c525f5 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  1191   1191       }else{
  1192   1192         int rc = sqlite3_reset(pCsr->pStmt);
  1193   1193         if( rc==SQLITE_OK ){
  1194   1194           /* If no row was found and no error has occured, then the %_content
  1195   1195           ** table is missing a row that is present in the full-text index.
  1196   1196           ** The data structures are corrupt.
  1197   1197           */
  1198         -        rc = SQLITE_CORRUPT;
         1198  +        rc = SQLITE_CORRUPT_VTAB;
  1199   1199         }
  1200   1200         pCsr->isEof = 1;
  1201   1201         if( pContext ){
  1202   1202           sqlite3_result_error_code(pContext, rc);
  1203   1203         }
  1204   1204         return rc;
  1205   1205       }
................................................................................
  1251   1251     ** contents, or two zero bytes. Or, if the node is read from the %_segments
  1252   1252     ** table, then there are always 20 bytes of zeroed padding following the
  1253   1253     ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
  1254   1254     */
  1255   1255     zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
  1256   1256     zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
  1257   1257     if( zCsr>zEnd ){
  1258         -    return SQLITE_CORRUPT;
         1258  +    return SQLITE_CORRUPT_VTAB;
  1259   1259     }
  1260   1260     
  1261   1261     while( zCsr<zEnd && (piFirst || piLast) ){
  1262   1262       int cmp;                      /* memcmp() result */
  1263   1263       int nSuffix;                  /* Size of term suffix */
  1264   1264       int nPrefix = 0;              /* Size of term prefix */
  1265   1265       int nBuffer;                  /* Total term size */
................................................................................
  1269   1269       if( !isFirstTerm ){
  1270   1270         zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
  1271   1271       }
  1272   1272       isFirstTerm = 0;
  1273   1273       zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
  1274   1274       
  1275   1275       if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
  1276         -      rc = SQLITE_CORRUPT;
         1276  +      rc = SQLITE_CORRUPT_VTAB;
  1277   1277         goto finish_scan;
  1278   1278       }
  1279   1279       if( nPrefix+nSuffix>nAlloc ){
  1280   1280         char *zNew;
  1281   1281         nAlloc = (nPrefix+nSuffix) * 2;
  1282   1282         zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
  1283   1283         if( !zNew ){

Changes to ext/fts3/fts3_snippet.c.

   956    956       if( rc!=SQLITE_OK ) return rc;
   957    957     }
   958    958     pStmt = *ppStmt;
   959    959     assert( sqlite3_data_count(pStmt)==1 );
   960    960   
   961    961     a = sqlite3_column_blob(pStmt, 0);
   962    962     a += sqlite3Fts3GetVarint(a, &nDoc);
   963         -  if( nDoc==0 ) return SQLITE_CORRUPT;
          963  +  if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
   964    964     *pnDoc = (u32)nDoc;
   965    965   
   966    966     if( paLen ) *paLen = a;
   967    967     return SQLITE_OK;
   968    968   }
   969    969   
   970    970   /*
................................................................................
  1551   1551           if( rc==SQLITE_OK ){
  1552   1552             char aBuffer[64];
  1553   1553             sqlite3_snprintf(sizeof(aBuffer), aBuffer, 
  1554   1554                 "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
  1555   1555             );
  1556   1556             rc = fts3StringAppend(&res, aBuffer, -1);
  1557   1557           }else if( rc==SQLITE_DONE ){
  1558         -          rc = SQLITE_CORRUPT;
         1558  +          rc = SQLITE_CORRUPT_VTAB;
  1559   1559           }
  1560   1560         }
  1561   1561       }
  1562   1562       if( rc==SQLITE_DONE ){
  1563   1563         rc = SQLITE_OK;
  1564   1564       }
  1565   1565   

Changes to ext/fts3/fts3_write.c.

   287    287     if( rc==SQLITE_OK ){
   288    288       if( eStmt==SQL_SELECT_DOCSIZE ){
   289    289         sqlite3_bind_int64(pStmt, 1, iDocid);
   290    290       }
   291    291       rc = sqlite3_step(pStmt);
   292    292       if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
   293    293         rc = sqlite3_reset(pStmt);
   294         -      if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT;
          294  +      if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
   295    295         pStmt = 0;
   296    296       }else{
   297    297         rc = SQLITE_OK;
   298    298       }
   299    299     }
   300    300   
   301    301     *ppStmt = pStmt;
................................................................................
   968    968     ** safe (no risk of overread) even if the node data is corrupted.  
   969    969     */
   970    970     pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
   971    971     pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
   972    972     if( nPrefix<0 || nSuffix<=0 
   973    973      || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] 
   974    974     ){
   975         -    return SQLITE_CORRUPT;
          975  +    return SQLITE_CORRUPT_VTAB;
   976    976     }
   977    977   
   978    978     if( nPrefix+nSuffix>pReader->nTermAlloc ){
   979    979       int nNew = (nPrefix+nSuffix)*2;
   980    980       char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
   981    981       if( !zNew ){
   982    982         return SQLITE_NOMEM;
................................................................................
   994    994     /* Check that the doclist does not appear to extend past the end of the
   995    995     ** b-tree node. And that the final byte of the doclist is 0x00. If either 
   996    996     ** of these statements is untrue, then the data structure is corrupt.
   997    997     */
   998    998     if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] 
   999    999      || pReader->aDoclist[pReader->nDoclist-1]
  1000   1000     ){
  1001         -    return SQLITE_CORRUPT;
         1001  +    return SQLITE_CORRUPT_VTAB;
  1002   1002     }
  1003   1003     return SQLITE_OK;
  1004   1004   }
  1005   1005   
  1006   1006   /*
  1007   1007   ** Set the SegReader to point to the first docid in the doclist associated
  1008   1008   ** with the current term.
................................................................................
  1119   1119         pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
  1120   1120         a += sqlite3Fts3GetVarint(a, &nDoc);
  1121   1121         while( a<pEnd ){
  1122   1122           a += sqlite3Fts3GetVarint(a, &nByte);
  1123   1123         }
  1124   1124         if( nDoc==0 || nByte==0 ){
  1125   1125           sqlite3_reset(pStmt);
  1126         -        return SQLITE_CORRUPT;
         1126  +        return SQLITE_CORRUPT_VTAB;
  1127   1127         }
  1128   1128   
  1129   1129         pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
  1130   1130         assert( pCsr->nRowAvg>0 ); 
  1131   1131         rc = sqlite3_reset(pStmt);
  1132   1132         if( rc!=SQLITE_OK ) return rc;
  1133   1133       }
................................................................................
  2758   2758       iRemove = sqlite3_value_int64(apVal[0]);
  2759   2759     }
  2760   2760     
  2761   2761     /* If this is an INSERT or UPDATE operation, insert the new record. */
  2762   2762     if( nArg>1 && rc==SQLITE_OK ){
  2763   2763       if( bInsertDone==0 ){
  2764   2764         rc = fts3InsertData(p, apVal, pRowid);
  2765         -      if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT;
         2765  +      if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
  2766   2766       }
  2767   2767       if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
  2768   2768         rc = fts3PendingTermsDocid(p, *pRowid);
  2769   2769       }
  2770   2770       if( rc==SQLITE_OK ){
  2771   2771         rc = fts3InsertTerms(p, apVal, aSzIns);
  2772   2772       }

Changes to ext/rtree/rtree.c.

   513    513     ** the root node. A height of one means the children of the root node
   514    514     ** are the leaves, and so on. If the depth as specified on the root node
   515    515     ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
   516    516     */
   517    517     if( pNode && iNode==1 ){
   518    518       pRtree->iDepth = readInt16(pNode->zData);
   519    519       if( pRtree->iDepth>RTREE_MAX_DEPTH ){
   520         -      rc = SQLITE_CORRUPT;
          520  +      rc = SQLITE_CORRUPT_VTAB;
   521    521       }
   522    522     }
   523    523   
   524    524     /* If no error has occurred so far, check if the "number of entries"
   525    525     ** field on the node is too large. If so, set the return code to 
   526         -  ** SQLITE_CORRUPT.
          526  +  ** SQLITE_CORRUPT_VTAB.
   527    527     */
   528    528     if( pNode && rc==SQLITE_OK ){
   529    529       if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
   530         -      rc = SQLITE_CORRUPT;
          530  +      rc = SQLITE_CORRUPT_VTAB;
   531    531       }
   532    532     }
   533    533   
   534    534     if( rc==SQLITE_OK ){
   535    535       if( pNode!=0 ){
   536    536         nodeHashInsert(pRtree, pNode);
   537    537       }else{
   538         -      rc = SQLITE_CORRUPT;
          538  +      rc = SQLITE_CORRUPT_VTAB;
   539    539       }
   540    540       *ppNode = pNode;
   541    541     }else{
   542    542       sqlite3_free(pNode);
   543    543       *ppNode = 0;
   544    544     }
   545    545   
................................................................................
  1058   1058     int nCell = NCELL(pNode);
  1059   1059     for(ii=0; ii<nCell; ii++){
  1060   1060       if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
  1061   1061         *piIndex = ii;
  1062   1062         return SQLITE_OK;
  1063   1063       }
  1064   1064     }
  1065         -  return SQLITE_CORRUPT;
         1065  +  return SQLITE_CORRUPT_VTAB;
  1066   1066   }
  1067   1067   
  1068   1068   /*
  1069   1069   ** Return the index of the cell containing a pointer to node pNode
  1070   1070   ** in its parent. If pNode is the root node, return -1.
  1071   1071   */
  1072   1072   static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
................................................................................
  1653   1653     RtreeNode *p = pNode;
  1654   1654     while( p->pParent ){
  1655   1655       RtreeNode *pParent = p->pParent;
  1656   1656       RtreeCell cell;
  1657   1657       int iCell;
  1658   1658   
  1659   1659       if( nodeParentIndex(pRtree, p, &iCell) ){
  1660         -      return SQLITE_CORRUPT;
         1660  +      return SQLITE_CORRUPT_VTAB;
  1661   1661       }
  1662   1662   
  1663   1663       nodeGetCell(pRtree, pParent, iCell, &cell);
  1664   1664       if( !cellContains(pRtree, &cell, pCell) ){
  1665   1665         cellUnion(pRtree, &cell, pCell);
  1666   1666         nodeOverwriteCell(pRtree, pParent, &cell, iCell);
  1667   1667       }
................................................................................
  2325   2325         for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
  2326   2326         if( !pTest ){
  2327   2327           rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
  2328   2328         }
  2329   2329       }
  2330   2330       rc = sqlite3_reset(pRtree->pReadParent);
  2331   2331       if( rc==SQLITE_OK ) rc = rc2;
  2332         -    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
         2332  +    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
  2333   2333       pChild = pChild->pParent;
  2334   2334     }
  2335   2335     return rc;
  2336   2336   }
  2337   2337   
  2338   2338   static int deleteCell(Rtree *, RtreeNode *, int, int);
  2339   2339   

Changes to src/sqlite.h.in.

   449    449   #define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
   450    450   #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
   451    451   #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
   452    452   #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
   453    453   #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
   454    454   #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
   455    455   #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
          456  +#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
   456    457   
   457    458   /*
   458    459   ** CAPI3REF: Flags For File Open Operations
   459    460   **
   460    461   ** These bit values are intended for use in the
   461    462   ** 3rd parameter to the [sqlite3_open_v2()] interface and
   462    463   ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.

Changes to src/test1.c.

   159    159       case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
   160    160       case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
   161    161       case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
   162    162       case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
   163    163       case SQLITE_IOERR_CHECKRESERVEDLOCK:
   164    164                                  zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
   165    165       case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
          166  +    case SQLITE_CORRUPT_VTAB:        zName = "SQLITE_CORRUPT_VTAB";      break;
          167  +                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
   166    168       default:                         zName = "SQLITE_Unknown";           break;
   167    169     }
   168    170     return zName;
   169    171   }
   170    172   #define t1ErrorName sqlite3TestErrorName
   171    173   
   172    174   /*

Changes to test/fts3corrupt.test.

    36     36     foreach w {a b c d e f g h i j k l m n o} {
    37     37       execsql { INSERT INTO t1 VALUES($w) }
    38     38     }
    39     39   } {}
    40     40   do_catchsql_test 1.3 {
    41     41     INSERT INTO t1 VALUES('world');
    42     42   } {1 {database disk image is malformed}}
           43  +do_test 1.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
    43     44   do_execsql_test 1.4 { 
    44     45     DROP TABLE t1;
    45     46   } 
    46     47   
    47     48   # This block of tests checks that corruption is correctly detected if the
    48     49   # length field of a term on a leaf node indicates that the term extends past
    49     50   # the end of the node on which it resides. There are two cases:
................................................................................
    65     66     set blob [db one {SELECT root from t1_segdir}]
    66     67     set blob [binary format a*a* "\x00\x7F" [string range $blob 2 end]]
    67     68     execsql { UPDATE t1_segdir SET root = $blob }
    68     69   } {}
    69     70   do_catchsql_test 2.2 {
    70     71     SELECT rowid FROM t1 WHERE t1 MATCH 'hello'
    71     72   } {1 {database disk image is malformed}}
           73  +do_test 2.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
    72     74   
    73     75   do_execsql_test 3.0 {
    74     76     DROP TABLE t1;
    75     77     CREATE VIRTUAL TABLE t1 USING fts3;
    76     78     BEGIN;
    77     79       INSERT INTO t1 VALUES('hello');
    78     80       INSERT INTO t1 VALUES('world');
................................................................................
    82     84     set blob [db one {SELECT quote(root) from t1_segdir}]
    83     85     set blob [binary format a11a*a* $blob "\x7F" [string range $blob 12 end]]
    84     86     execsql { UPDATE t1_segdir SET root = $blob }
    85     87   } {}
    86     88   do_catchsql_test 3.2 {
    87     89     SELECT rowid FROM t1 WHERE t1 MATCH 'world'
    88     90   } {1 {database disk image is malformed}}
           91  +do_test 3.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
    89     92   
    90     93   
    91     94   do_execsql_test 4.0 {
    92     95     DROP TABLE t1;
    93     96     CREATE VIRTUAL TABLE t1 USING fts3;
    94     97     INSERT INTO t1(t1) VALUES('nodesize=24');
    95     98   }
................................................................................
   107    110     execsql COMMIT
   108    111   } {}
   109    112   
   110    113   do_catchsql_test 4.2 {
   111    114     UPDATE t1_segdir SET root = X'FFFFFFFFFFFFFFFF';
   112    115     SELECT rowid FROM t1 WHERE t1 MATCH 'world';
   113    116   } {1 {database disk image is malformed}}
          117  +do_test 4.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
   114    118   
   115    119   set    blob [binary format cca*cca*cca*cca*cca*cca*cca*cca*cca*cca*a* \
   116    120     22 120 [string repeat a 120]  \
   117    121     22 120 [string repeat b 120]  \
   118    122     22 120 [string repeat c 120]  \
   119    123     22 120 [string repeat d 120]  \
   120    124     22 120 [string repeat e 120]  \
................................................................................
   126    130     "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
   127    131   ]
   128    132   
   129    133   do_catchsql_test 4.3 {
   130    134     UPDATE t1_segdir SET root = $blob;
   131    135     SELECT rowid FROM t1 WHERE t1 MATCH 'world';
   132    136   } {1 {database disk image is malformed}}
          137  +do_test 4.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
   133    138   
   134    139   # Test a special kind of corruption, where the %_stat table contains
   135    140   # an invalid entry. At one point this could lead to a division-by-zero
   136    141   # error in fts4.
   137    142   #
   138    143   do_execsql_test 5.0 {
   139    144     DROP TABLE t1;
................................................................................
   148    153     execsql { INSERT INTO t1 VALUES('four') }
   149    154     execsql COMMIT
   150    155   } {}
   151    156   do_catchsql_test 5.2 {
   152    157     UPDATE t1_stat SET value = X'0000';
   153    158     SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
   154    159   } {1 {database disk image is malformed}}
          160  +do_test 5.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
   155    161   do_catchsql_test 5.3 {
   156    162     UPDATE t1_stat SET value = NULL;
   157    163     SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
   158    164   } {1 {database disk image is malformed}}
          165  +do_test 5.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
   159    166   
   160    167   
   161    168   finish_test
   162    169