/ Check-in [7aecabac]
Login

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

Overview
Comment:Fix a case where database corruption was causing an invalid reference. (CVS 5484)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7aecabacf924ad8c1f9f4e707d0c56e433e3a434
User & Date: danielk1977 2008-07-26 18:26:10
Context
2008-07-26
18:47
Remove a branch that could not be taken from OP_IsUnique. (CVS 5485) check-in: 75c2a532 user: danielk1977 tags: trunk
18:26
Fix a case where database corruption was causing an invalid reference. (CVS 5484) check-in: 7aecabac user: danielk1977 tags: trunk
2008-07-25
16:39
Add an SQLITE_OMIT_LOCALTIME around the "utc" modifier in date/time functions. (CVS 5483) check-in: 71486e93 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.763 2008/07/23 21:07:25 drh Exp $
           46  +** $Id: vdbe.c,v 1.764 2008/07/26 18:26:10 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
  3132   3132   
  3133   3133       /* Make sure K is a string and make zKey point to K
  3134   3134       */
  3135   3135       assert( pK->flags & MEM_Blob );
  3136   3136       zKey = pK->z;
  3137   3137       nKey = pK->n;
  3138   3138   
  3139         -    szRowid = sqlite3VdbeIdxRowidLen((u8*)zKey);
         3139  +    rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
         3140  +    if( rc!=SQLITE_OK ){
         3141  +      goto abort_due_to_error;
         3142  +    }
  3140   3143       len = nKey-szRowid;
  3141   3144   
  3142   3145       /* Search for an entry in P1 where all but the last four bytes match K.
  3143   3146       ** If there is no such entry, jump immediately to P2.
  3144   3147       */
  3145   3148       assert( pCx->deferredMoveto==0 );
  3146   3149       pCx->cacheStatus = CACHE_STALE;

Changes to src/vdbeInt.h.

    11     11   *************************************************************************
    12     12   ** This is the header file for information that is private to the
    13     13   ** VDBE.  This information used to all be at the top of the single
    14     14   ** source code file "vdbe.c".  When that file became too big (over
    15     15   ** 6000 lines long) it was split up into several smaller files and
    16     16   ** this header information was factored out.
    17     17   **
    18         -** $Id: vdbeInt.h,v 1.149 2008/06/25 00:12:41 drh Exp $
           18  +** $Id: vdbeInt.h,v 1.150 2008/07/26 18:26:10 danielk1977 Exp $
    19     19   */
    20     20   #ifndef _VDBEINT_H_
    21     21   #define _VDBEINT_H_
    22     22   
    23     23   /*
    24     24   ** intToKey() and keyToInt() used to transform the rowid.  But with
    25     25   ** the latest versions of the design they are no-ops.
................................................................................
   386    386   int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
   387    387   void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
   388    388   
   389    389   int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
   390    390   int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
   391    391   int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
   392    392   int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
   393         -int sqlite3VdbeIdxRowidLen(const u8*);
          393  +int sqlite3VdbeIdxRowidLen(const u8*, int, int*);
   394    394   int sqlite3VdbeExec(Vdbe*);
   395    395   int sqlite3VdbeList(Vdbe*);
   396    396   int sqlite3VdbeHalt(Vdbe*);
   397    397   int sqlite3VdbeChangeEncoding(Mem *, int);
   398    398   int sqlite3VdbeMemTooBig(Mem*);
   399    399   int sqlite3VdbeMemCopy(Mem*, const Mem*);
   400    400   void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.399 2008/07/22 05:18:01 shane Exp $
           17  +** $Id: vdbeaux.c,v 1.400 2008/07/26 18:26:10 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   
    24     24   
................................................................................
  2350   2350   
  2351   2351   /*
  2352   2352   ** The argument is an index entry composed using the OP_MakeRecord opcode.
  2353   2353   ** The last entry in this record should be an integer (specifically
  2354   2354   ** an integer rowid).  This routine returns the number of bytes in
  2355   2355   ** that integer.
  2356   2356   */
  2357         -int sqlite3VdbeIdxRowidLen(const u8 *aKey){
         2357  +int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
  2358   2358     u32 szHdr;        /* Size of the header */
  2359   2359     u32 typeRowid;    /* Serial type of the rowid */
  2360   2360   
  2361   2361     (void)getVarint32(aKey, szHdr);
         2362  +  if( szHdr>nKey ){
         2363  +    return SQLITE_CORRUPT_BKPT;
         2364  +  }
  2362   2365     (void)getVarint32(&aKey[szHdr-1], typeRowid);
  2363         -  return sqlite3VdbeSerialTypeLen(typeRowid);
         2366  +  *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
         2367  +  return SQLITE_OK;
  2364   2368   }
  2365   2369     
  2366   2370   
  2367   2371   /*
  2368   2372   ** pCur points at an index entry created using the OP_MakeRecord opcode.
  2369   2373   ** Read the rowid (the last field in the record) and store it in *rowid.
  2370   2374   ** Return SQLITE_OK if everything works, or an error code otherwise.
................................................................................
  2425   2429     if( nCellKey<=0 ){
  2426   2430       *res = 0;
  2427   2431       return SQLITE_OK;
  2428   2432     }
  2429   2433     m.db = 0;
  2430   2434     m.flags = 0;
  2431   2435     m.zMalloc = 0;
  2432         -  rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
  2433         -  if( rc ){
         2436  +  if( (rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m))
         2437  +   || (rc = sqlite3VdbeIdxRowidLen((u8*)m.z, m.n, &lenRowid))
         2438  +  ){
  2434   2439       return rc;
  2435   2440     }
  2436         -  lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
  2437   2441     if( !pUnpacked ){
  2438   2442       pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
  2439   2443                                   zSpace, sizeof(zSpace));
  2440   2444     }else{
  2441   2445       pRec = pUnpacked;
  2442   2446     }
  2443   2447     if( pRec==0 ){

Changes to test/corrupt7.test.

    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests to make sure SQLite does not crash or
    14     14   # segfault if it sees a corrupt database file.  It specifically focuses
    15     15   # on corrupt cell offsets in a btree page.
    16     16   #
    17         -# $Id: corrupt7.test,v 1.3 2008/07/25 14:53:17 drh Exp $
           17  +# $Id: corrupt7.test,v 1.4 2008/07/26 18:26:10 danielk1977 Exp $
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22     22   # We must have the page_size pragma for these tests to work.
    23     23   #
    24     24   ifcapable !pager_pragmas {
................................................................................
    68     68     db close
    69     69     hexio_write test.db 1062 04
    70     70     sqlite3 db test.db
    71     71     db eval {PRAGMA integrity_check(1)}
    72     72   } {{*** in database main ***
    73     73   Corruption detected in cell 15 on page 2}}
    74     74   
           75  +do_test corrupt7-3.1 {
           76  +  execsql {
           77  +    DROP TABLE t1;
           78  +    CREATE TABLE t1(a, b);
           79  +    INSERT INTO t1 VALUES(1, 'one');
           80  +    INSERT INTO t1 VALUES(100, 'one hundred');
           81  +    INSERT INTO t1 VALUES(100000, 'one hundred thousand');
           82  +    CREATE INDEX i1 ON t1(b);
           83  +  }
           84  +  db close
           85  +
           86  +  # Locate the 3rd cell in the index.
           87  +  set cell_offset [hexio_get_int [hexio_read test.db [expr 1024*2 + 12] 2]]
           88  +  incr cell_offset [expr 1024*2]
           89  +  incr cell_offset 1
           90  +
           91  +  # This write corrupts the "header-size" field of the database record
           92  +  # stored in the index cell. At one point this was causing sqlite to 
           93  +  # reference invalid memory.
           94  +  hexio_write test.db $cell_offset FFFF7F
           95  +  
           96  +  sqlite3 db test.db
           97  +  catchsql {
           98  +    SELECT b FROM t1 WHERE b > 'o' AND b < 'p';
           99  +  }
          100  +} {1 {database disk image is malformed}}
          101  +
    75    102   finish_test