From: danielk1977 Date: Thu, 3 Apr 2008 14:36:25 +0000 (+0000) Subject: Avoid an out-of-bounds read in sqlite3_prepare() and fix a case where the output... X-Git-Tag: version-3.5.8~62 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3a2c8c8b7381b3751c6d0cb8ae539ba9cef44fa8;p=thirdparty%2Fsqlite.git Avoid an out-of-bounds read in sqlite3_prepare() and fix a case where the output variable *pzTail was being set incorrectly. Fix for #3027. (CVS 4957) FossilOrigin-Name: c287a7b29410be12cf88f886e8e2525a42aa9c03 --- diff --git a/manifest b/manifest index a9de21cf41..07b2119dd4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sallocator\sin\smem2.c\s(used\swhen\sSQLITE_MEMDEBUG\sis\sdefined)\sso\sthat\sallocations\sare\snot\srounded\sup\sto\sthe\snearest\s4\sbyte\sboundary.\sFix\sa\scouple\sof\serrors\sin\smalloc.test\srelated\sto\ssqlite3OsAccess()\sreturning\s-1.\s(CVS\s4956) -D 2008-04-03T10:13:01 +C Avoid\san\sout-of-bounds\sread\sin\ssqlite3_prepare()\sand\sfix\sa\scase\swhere\sthe\soutput\svariable\s*pzTail\swas\sbeing\sset\sincorrectly.\sFix\sfor\s#3027.\s(CVS\s4957) +D 2008-04-03T14:36:26 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in b861627d91df5ee422c54237aa38296954dc0151 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -132,19 +132,19 @@ F src/pager.c 7b302d90674ea411d0856057af9699fe003318e3 F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170 F src/parse.y bc1b1cc6f86a0e0b669abdd88ddbdc7c8b67318d F src/pragma.c e659c9e443d11854cff2fd250012365ae0ca81ba -F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c +F src/prepare.c adc7e1fc08dfbab63cd213d4c0aff8f3fa70d477 F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a F src/select.c 53bfb7c4da43b2d20f27b5bf0ceab94d53835080 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d -F src/sqlite.h.in b1ac824d9fc163a5d2226ebf5990b09a02a11117 +F src/sqlite.h.in 5364513316e0c36cb02b27c479643b400dbde9c7 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3 F src/sqliteInt.h cfe0b6c4b1a9b4be22f856ca8058ccd1bf0e41a8 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda -F src/test1.c 342a2628310fa709074d979e695a28a3bb570834 +F src/test1.c 318bed2bfc24b9f454af09c408ffe4a94d03b9e9 F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121 F src/test3.c c715b5a8a6415d7b2c67f97c394eef488b6f7e63 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 @@ -218,7 +218,7 @@ F test/blob.test f2dbdbf1159674283645c2636436839313ee7131 F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9 F test/capi2.test cc64df7560a96f848f919ea2926c60acf639684b -F test/capi3.test 928999c4fb7c70239a4c7b8f9fa52d5cdba9b568 +F test/capi3.test 8113010cd06a94b7ac72524858968069b7cac8e3 F test/capi3b.test 664eb55318132f292f2c436f90906f578cad6b97 F test/capi3c.test 976673c1c5caef84201473ea5f7bb7b3093935a8 F test/cast.test ce8f14fc80f70b30ed984480cc0d8914a459e8f9 @@ -246,6 +246,7 @@ F test/crash3.test 0b09687ae1a3ccbcefdfaeb4b963e26e36255d76 F test/crash4.test 02ff4f15c149ca1e88a5c299b4896c84d9450c3b F test/crash5.test c7ddcf7ca83abc19901b977732144234ac72a938 F test/crash6.test 873d851c5ba2a46e0f9974c54e1d4a77d9a587d5 +F test/crash7.test e20a7b9ee1d16eaef7c94a4cb7ed2191b4d05970 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272 F test/cse.test 4b8a49decaefccb835ecc67249277be491713f6c @@ -519,6 +520,7 @@ F test/utf16.test 20e2d9ba0d57e952a18b1ac8deab9ad49e082893 F test/utf16align.test 7360e84472095518c56746f76b1f9d4dce99fb4d F test/vacuum.test f67853a15caa120af591f819670f01a11fcc2bfc F test/vacuum2.test d3b9691541fe6ed5c711f547a1c7d70e9760ac6f +F test/vacuum3.test 72fbc903b085cd5f8b3a513b23f8ce44f7e0b06f F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 9bba6886026bb58a7332b6c96fd8270469f02177 F test/view.test 4864e3841ab3213a95297718b94d5d6a8d3bc78b @@ -621,7 +623,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P e8529455803e0dab167f4faba5846fa1eafef741 -R ad2bb86bdc9a3800369a1a0fec7f9426 +P fd97f8762cb1e4653c932402940f74d7c0ebf71f +R 4cbad59c692acf4f8287734f3525dd14 U danielk1977 -Z 8a37a96ffe96147a3305789b321aea9b +Z e74a22ea6ae0b08ba9441bfc8876ae6c diff --git a/manifest.uuid b/manifest.uuid index 12c3213bf5..ba9f5ef27c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fd97f8762cb1e4653c932402940f74d7c0ebf71f \ No newline at end of file +c287a7b29410be12cf88f886e8e2525a42aa9c03 \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index bdb3d37c02..b52667801b 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.82 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: prepare.c,v 1.83 2008/04/03 14:36:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -552,7 +552,7 @@ static int sqlite3Prepare( memset(&sParse, 0, sizeof(sParse)); sParse.db = db; - if( nBytes>=0 && zSql[nBytes]!=0 ){ + if( nBytes>=0 && zSql[nBytes-1]!=0 ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( nBytes>mxLen ){ @@ -564,8 +564,10 @@ static int sqlite3Prepare( if( zSqlCopy ){ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); sqlite3_free(zSqlCopy); + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; + }else{ + sParse.zTail = &zSql[nBytes]; } - sParse.zTail = &zSql[nBytes]; }else{ sqlite3RunParser(&sParse, zSql, &zErrMsg); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d6c68ccb2c..c713988d8d 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.301 2008/03/26 18:34:43 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.302 2008/04/03 14:36:26 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -2292,7 +2292,11 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** If nByte is non-negative, then it is the maximum number of ** bytes read from zSql. When nByte is non-negative, the ** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} +** until the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be had by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes.{END} ** ** *pzTail is made to point to the first byte past the end of the ** first SQL statement in zSql. These routines only compiles the first diff --git a/src/test1.c b/src/test1.c index 25846ad24b..5b477a83ac 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.295 2008/03/22 01:07:18 drh Exp $ +** $Id: test1.c,v 1.296 2008/04/03 14:36:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -3052,6 +3052,9 @@ static int test_prepare( if( bytes>=0 ){ bytes = bytes - (zTail-zSql); } + if( strlen(zTail)>2)&3)] + + execsql " + PRAGMA page_size = $from_size; + BEGIN; + CREATE TABLE abc(a PRIMARY KEY, b, c); + INSERT INTO abc VALUES(randomblob(100), randomblob(200), randomblob(1000)); + INSERT INTO abc + SELECT randomblob(1000), randomblob(200), randomblob(100) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc WHERE [expr $ii&16]; + INSERT INTO abc + SELECT randomblob(25), randomblob(45), randomblob(9456) + FROM abc WHERE [expr $ii&32]; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc WHERE [expr $ii&8]; + INSERT INTO abc + SELECT randomblob(25), randomblob(45), randomblob(9456) + FROM abc WHERE [expr $ii&4]; + COMMIT; + " + + set sig [signature] + db close + + do_test crash7-1.$ii.crash { + crashsql -file $f " + PRAGMA page_size = $to_size; + VACUUM; + " + } {1 {child process exited abnormally}} + + sqlite3 db test.db + integrity_check crash7-1.$ii.integrity + } +} + +finish_test diff --git a/test/vacuum3.test b/test/vacuum3.test new file mode 100644 index 0000000000..342e4596a9 --- /dev/null +++ b/test/vacuum3.test @@ -0,0 +1,268 @@ +# 2007 March 19 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is changing the database page size using a +# VACUUM statement. +# +# $Id: vacuum3.test,v 1.1 2008/04/03 14:36:26 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# If the VACUUM statement is disabled in the current build, skip all +# the tests in this file. +# +ifcapable !vacuum { + finish_test + return +} + + +#------------------------------------------------------------------- +# Test cases vacuum3-1.* convert a simple 2-page database between a +# few different page sizes. +# +do_test vacuum3-1.1 { + execsql { + PRAGMA page_size = 1024; + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1, 2, 3); + } +} {} +do_test vacuum3-1.2 { + execsql { PRAGMA page_size } +} {1024} +do_test vacuum3-1.3 { + file size test.db +} {2048} + +set I 4 +foreach {request actual database} [list \ + 2048 2048 4096 \ + 1024 1024 2048 \ + 1170 1024 2048 \ + 256 1024 2048 \ + 512 512 1024 \ + 4096 4096 8192 \ + 1024 1024 2048 \ +] { +if {$I==10} breakpoint + do_test vacuum3-1.$I.1 { + execsql " + PRAGMA page_size = $request; + VACUUM; + " + execsql { PRAGMA page_size } + } $actual + do_test vacuum3-1.$I.2 { + file size test.db + } $database + do_test vacuum3-1.$I.3 { + execsql { SELECT * FROM t1 } + } {1 2 3} + integrity_check vacuum3-1.$I.4 + + incr I +} + +#------------------------------------------------------------------- +# Test cases vacuum3-2.* convert a simple 3-page database between a +# few different page sizes. +# +do_test vacuum3-2.1 { + execsql { + PRAGMA page_size = 1024; + VACUUM; + ALTER TABLE t1 ADD COLUMN d; + UPDATE t1 SET d = randomblob(1000); + } + file size test.db +} {3072} +do_test vacuum3-2.2 { + execsql { PRAGMA page_size } +} {1024} +do_test vacuum3-2.3 { + set blob [db one {select d from t1}] + string length $blob +} {1000} + +set I 4 +foreach {request actual database} [list \ + 2048 2048 4096 \ + 1024 1024 3072 \ + 1170 1024 3072 \ + 256 1024 3072 \ + 512 512 2048 \ + 4096 4096 8192 \ + 1024 1024 3072 \ +] { +if {$I==10} breakpoint + do_test vacuum3-2.$I.1 { + execsql " + PRAGMA page_size = $request; + VACUUM; + " + execsql { PRAGMA page_size } + } $actual + do_test vacuum3-2.$I.2 { + file size test.db + } $database + do_test vacuum3-2.$I.3 { + execsql { SELECT * FROM t1 } + } [list 1 2 3 $blob] + integrity_check vacuum3-1.$I.4 + + incr I +} + +#------------------------------------------------------------------- +# Test cases vacuum3-3.* converts a database large enough to include +# the locking page (in a test environment) between few different +# page sizes. +# +proc signature {} { + return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}] +} +do_test vacuum3-3.1 { + execsql " + PRAGMA page_size = 1024; + BEGIN; + CREATE TABLE abc(a PRIMARY KEY, b, c); + INSERT INTO abc VALUES(randomblob(100), randomblob(200), randomblob(1000)); + INSERT INTO abc + SELECT randomblob(1000), randomblob(200), randomblob(100) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(25), randomblob(45), randomblob(9456) + FROM abc; + INSERT INTO abc + SELECT randomblob(100), randomblob(200), randomblob(1000) + FROM abc; + INSERT INTO abc + SELECT randomblob(25), randomblob(45), randomblob(9456) + FROM abc; + COMMIT; + " +} {} +do_test vacuum3-3.2 { + execsql { PRAGMA page_size } +} {1024} + +set ::sig [signature] + +set I 3 +foreach {request actual} [list \ + 2048 2048 \ + 1024 1024 \ + 1170 1024 \ + 256 1024 \ + 512 512 \ + 4096 4096 \ + 1024 1024 \ +] { +if {$I==10} breakpoint + do_test vacuum3-3.$I.1 { + execsql " + PRAGMA page_size = $request; + VACUUM; + " + execsql { PRAGMA page_size } + } $actual + do_test vacuum3-3.$I.2 { + signature + } $::sig + integrity_check vacuum3-3.$I.3 + + incr I +} + +do_ioerr_test vacuum3-ioerr-1 -cksum true -sqlprep { + PRAGMA page_size = 1024; + BEGIN; + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1, randstr(50,50), randstr(50,50)); + INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 VALUES(1, randstr(600,600), randstr(600,600)); + CREATE TABLE t2 AS SELECT * FROM t1; + CREATE TABLE t3 AS SELECT * FROM t1; + COMMIT; + DROP TABLE t2; +} -sqlbody { + PRAGMA page_size = 4096; + VACUUM; +} +do_ioerr_test vacuum3-ioerr-2 -cksum true -sqlprep { + PRAGMA page_size = 2048; + BEGIN; + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1, randstr(50,50), randstr(50,50)); + INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 VALUES(1, randstr(600,600), randstr(600,600)); + CREATE TABLE t2 AS SELECT * FROM t1; + CREATE TABLE t3 AS SELECT * FROM t1; + COMMIT; + DROP TABLE t2; +} -sqlbody { + PRAGMA page_size = 512; + VACUUM; +} + +source $testdir/malloc_common.tcl +if {$MEMDEBUG} { + do_malloc_test vacuum3-malloc-1 -sqlprep { + PRAGMA page_size = 2048; + BEGIN; + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1, randstr(50,50), randstr(50,50)); + INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1; + INSERT INTO t1 VALUES(1, randstr(600,600), randstr(600,600)); + CREATE TABLE t2 AS SELECT * FROM t1; + CREATE TABLE t3 AS SELECT * FROM t1; + COMMIT; + DROP TABLE t2; + } -sqlbody { + PRAGMA page_size = 512; + VACUUM; + } +} + +finish_test +