/ Check-in [c3baca99]
Login

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

Overview
Comment:Make sure signed integer overflow does not cause a segfault while attempting to read a corrupt database where the header size varint on a record is larger than the maximum 32-bit signed integer.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c3baca99f4580652afb2c3f73036ab83796a1557
User & Date: drh 2013-08-01 19:17:39
Context
2013-08-01
20:26
Fix a potential buffer overread in sqlite3VdbeRecordCompare() when a serial_type specifies a field that starts in bounds but is much too large for the allocated buffer. Mostly harmless. The overread is unlikely to go more than one or two bytes past the end of the buffer. check-in: e436b2f4 user: drh tags: trunk
19:17
Make sure signed integer overflow does not cause a segfault while attempting to read a corrupt database where the header size varint on a record is larger than the maximum 32-bit signed integer. check-in: c3baca99 user: drh tags: trunk
17:43
Add test case for the problem fixed by [127a5b776d]. check-in: 65816718 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbeaux.c.

  2986   2986   ** equal, then the keys are considered to be equal and
  2987   2987   ** the parts beyond the common prefix are ignored.
  2988   2988   */
  2989   2989   int sqlite3VdbeRecordCompare(
  2990   2990     int nKey1, const void *pKey1, /* Left key */
  2991   2991     UnpackedRecord *pPKey2        /* Right key */
  2992   2992   ){
  2993         -  int d1;            /* Offset into aKey[] of next data element */
         2993  +  u32 d1;            /* Offset into aKey[] of next data element */
  2994   2994     u32 idx1;          /* Offset into aKey[] of next header element */
  2995   2995     u32 szHdr1;        /* Number of bytes in header */
  2996   2996     int i = 0;
  2997   2997     int nField;
  2998   2998     int rc = 0;
  2999   2999     const unsigned char *aKey1 = (const unsigned char *)pKey1;
  3000   3000     KeyInfo *pKeyInfo;
................................................................................
  3020   3020     nField = pKeyInfo->nField;
  3021   3021     assert( pKeyInfo->aSortOrder!=0 );
  3022   3022     while( idx1<szHdr1 && i<pPKey2->nField ){
  3023   3023       u32 serial_type1;
  3024   3024   
  3025   3025       /* Read the serial types for the next element in each key. */
  3026   3026       idx1 += getVarint32( aKey1+idx1, serial_type1 );
  3027         -    if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
         3027  +    if( d1>=(u32)nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
  3028   3028   
  3029   3029       /* Extract the values to be compared.
  3030   3030       */
  3031   3031       d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
  3032   3032   
  3033   3033       /* Do the comparison
  3034   3034       */

Added test/corruptG.test.

            1  +# 2013-08-01
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +set testprefix corruptG
           16  +
           17  +# Do not use a codec for tests in this file, as the database file is
           18  +# manipulated directly using tcl scripts (using the [hexio_write] command).
           19  +#
           20  +do_not_use_codec
           21  +
           22  +# Create a simple database with a single entry.  Then corrupt the
           23  +# header-size varint on the index payload so that it maps into a
           24  +# negative number.  Try to use the database.
           25  +#
           26  +
           27  +do_execsql_test 1.1 {
           28  +  PRAGMA page_size=512;
           29  +  CREATE TABLE t1(a,b,c);
           30  +  INSERT INTO t1(rowid,a,b,c) VALUES(2,'abc','xyz','123');
           31  +  CREATE INDEX t1abc ON t1(a,b,c);
           32  +}
           33  +
           34  +# Corrupt the file
           35  +db close
           36  +hexio_write test.db [expr {3*512 - 15}] 888080807f
           37  +sqlite3 db test.db
           38  +
           39  +# Try to use the file.
           40  +do_test 1.2 {
           41  +  catchsql {
           42  +    SELECT c FROM t1 WHERE a>'abc';
           43  +  }
           44  +} {0 {}}
           45  +do_test 1.3 {
           46  +  catchsql {
           47  +     PRAGMA integrity_check
           48  +  }
           49  +} {0 ok}
           50  +do_test 1.4 {
           51  +  catchsql {
           52  +    SELECT c FROM t1 ORDER BY a;
           53  +  }
           54  +} {1 {database disk image is malformed}}
           55  +
           56  +finish_test