From: dan Date: Mon, 3 Mar 2014 20:48:50 +0000 (+0000) Subject: Avoid a buffer overread in vdbeCompareRecordInt() that might occur if the database... X-Git-Tag: version-3.8.4~34^2~2^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9b8afef260c0ed02cc0d1a195fa697844eb1c02e;p=thirdparty%2Fsqlite.git Avoid a buffer overread in vdbeCompareRecordInt() that might occur if the database is corrupt. FossilOrigin-Name: 7c0b4381f0e6f33cb13299a915851d9431bf3850 --- diff --git a/manifest b/manifest index 4302dac32e..1f36291c28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sa\scomment.\s\sNo\schanges\sto\scode. -D 2014-03-03T19:29:28.807 +C Avoid\sa\sbuffer\soverread\sin\svdbeCompareRecordInt()\sthat\smight\soccur\sif\sthe\sdatabase\sis\scorrupt. +D 2014-03-03T20:48:50.982 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c b817480055ea37f04cbda6524cbcda56d8620c78 +F src/vdbeaux.c 687165bd405b33553c9aaf5da74c249cea083d24 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -404,6 +404,7 @@ F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039 +F test/corruptI.test d9eca60cb373215d97e0994bf104f9a37e1ac0fc F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f @@ -1153,7 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ba8993727e5752cbc92c7d78437e9e0510c899f7 -R 84a57b7d3530d77238186688acf2fb15 -U drh -Z 743719e98998c2037f212aec24c916c8 +P 1f4991ab1676bf85599fc32068ceeddeb05f648c +R 112194c4c042293d2f5fc41663c08a7a +U dan +Z e0c8dc8360525071b6a4931f6b50a318 diff --git a/manifest.uuid b/manifest.uuid index 2f5a48fd68..f96d8cdcc1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f4991ab1676bf85599fc32068ceeddeb05f648c \ No newline at end of file +7c0b4381f0e6f33cb13299a915851d9431bf3850 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 47a3f0899b..dd724cc39e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3575,7 +3575,8 @@ static int vdbeRecordCompareInt( const UnpackedRecord *pPKey2, /* Right key */ int bSkip /* Ignored */ ){ - const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1]; + int szHdr = *(const u8*)pKey1; + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; int serial_type = ((const u8*)pKey1)[1]; int res; i64 v = pPKey2->aMem[0].u.i; @@ -3583,7 +3584,6 @@ static int vdbeRecordCompareInt( UNUSED_PARAMETER(bSkip); assert( bSkip==0 ); - switch( serial_type ){ case 1: lhs = (char)(aKey[0]); @@ -3718,12 +3718,20 @@ static int vdbeRecordCompareString( ** as the only argument. */ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ - /* As the varints that make up a record header are all 5 bytes in size - ** or less, if the binary keys being compared have 25 or fewer fields - ** then it is guaranteed that the varint at the start of every record - ** (the record-header size in bytes) fits in a single byte. If this - ** is not the case, then sqlite3VdbeRecordCompare() must be used. */ - if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=25 ){ + /* varintRecordCompareInt() and varintRecordCompareString() both assume + ** that the size-of-header varint that occurs at the start of each record + ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() + ** also assumes that it is safe to overread a buffer by at least the + ** maximum possible legal header size plus 8 bytes. Because there is + ** guaranteed to be at least 74 (but not 136) bytes of padding following each + ** buffer passed to varintRecordCompareInt() this makes it convenient to + ** limit the size of the header to 64 bytes in cases where the first field + ** is an integer. + ** + ** The easiest way to enforce this limit is to consider only records with + ** 13 fields or less. If the first field is an integer, the maximum legal + ** header size is (12*5 + 1 + 1) bytes. */ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortOrder[0] ){ p->r1 = 1; diff --git a/test/corruptI.test b/test/corruptI.test new file mode 100644 index 0000000000..9c9a19310b --- /dev/null +++ b/test/corruptI.test @@ -0,0 +1,47 @@ +# 2014-01-20 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix corruptI + +# Do not use a codec for tests in this file, as the database file is +# manipulated directly using tcl scripts (using the [hexio_write] command). +# +do_not_use_codec +database_may_be_corrupt + +# Initialize the database. +# +do_execsql_test 1.1 { + PRAGMA page_size=1024; + PRAGMA auto_vacuum=0; + CREATE TABLE t1(a); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES('a'); +} {} +db close + +do_test 1.2 { + set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] + set off [expr 2*1024 + $offset + 1] + hexio_write test.db $off FF06 + + breakpoint + + sqlite3 db test.db + catchsql { SELECT * FROM t1 WHERE a = 10 } +} {1 {database disk image is malformed}} + + +finish_test +