]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid ever writing before the start of an allocated buffer in the DIRECT_OVERFLOW_REA...
authordan <dan@noemail.net>
Thu, 21 May 2015 17:21:05 +0000 (17:21 +0000)
committerdan <dan@noemail.net>
Thu, 21 May 2015 17:21:05 +0000 (17:21 +0000)
FossilOrigin-Name: 31b13eb52894db75b52b6419bd9ec980b4c3ac43

manifest
manifest.uuid
src/btree.c
test/ovfl.test [new file with mode: 0644]

index 77e0613c85f1907ddefbbeb4bd932a46b204c4ac..ab3da2c9494fd8704c06aab43a5e04fa124b2e7c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\sin\stest\sfile\se_reindex.test.\sCherrypick\sof\s[5b3de9390f2f].
-D 2015-05-20T20:50:59.596
+C Avoid\sever\swriting\sbefore\sthe\sstart\sof\san\sallocated\sbuffer\sin\sthe\sDIRECT_OVERFLOW_READ\scode.\sFix\sfor\s[e3a290961a6].\sCherrypick\sof\s[c3c15d20c691].
+D 2015-05-21T17:21:05.934
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -167,7 +167,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c fa057e30794bfd867963b44a3a42710a45c335a1
+F src/btree.c 3baad8da3d3a8363348b70ddfacbcc3e82760e61
 F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
 F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b
@@ -742,6 +742,7 @@ F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
 F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
 F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
 F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
+F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
 F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
@@ -1186,8 +1187,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 7d7d633c71bb36bed98bc2c77d3268cc26fbac3e
-Q +5b3de9390f2ffc4c530fd47c71c70e87972cf74b
-R b85e8aeadcdd5ec4c54b45311910ff86
+P 80633682d714e5bedc129d8f579a46cc7c2040e6
+Q +c3c15d20c6913811956a5041c959a56ca4eeb5eb
+R a14351485096703f0ae3593f0280678f
 U dan
-Z e6c180a85390645dc9dfecdc10a4b12e
+Z 4475ac0ddfbc6008239591329b8dd6f2
index ecf3dae08a51c41a90716dca95e05b3a1a51db4d..015fd28767fce2a1c567de1e7930eb48d0b47986 100644 (file)
@@ -1 +1 @@
-80633682d714e5bedc129d8f579a46cc7c2040e6
\ No newline at end of file
+31b13eb52894db75b52b6419bd9ec980b4c3ac43
\ No newline at end of file
index 60bc7de41eb48d26fe9b1aef12cfe1836b2db0b1..860e27242b82f9b3e815e9fed325a79920e6f25c 100644 (file)
@@ -3967,7 +3967,8 @@ static int accessPayload(
   MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
   BtShared *pBt = pCur->pBt;                  /* Btree this cursor belongs to */
 #ifdef SQLITE_DIRECT_OVERFLOW_READ
-  int bEnd;                                   /* True if reading to end of data */
+  unsigned char * const pBufStart = pBuf;
+  int bEnd;                                 /* True if reading to end of data */
 #endif
 
   assert( pPage );
@@ -4094,6 +4095,7 @@ static int accessPayload(
         **   4) there is no open write-transaction, and
         **   5) the database is not a WAL database,
         **   6) all data from the page is being read.
+        **   7) at least 4 bytes have already been read into the output buffer 
         **
         ** then data can be read directly from the database file into the
         ** output buffer, bypassing the page-cache altogether. This speeds
@@ -4105,9 +4107,11 @@ static int accessPayload(
          && pBt->inTransaction==TRANS_READ                     /* (4) */
          && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
          && pBt->pPage1->aData[19]==0x01                       /* (5) */
+         && &pBuf[-4]>=pBufStart                               /* (7) */
         ){
           u8 aSave[4];
           u8 *aWrite = &pBuf[-4];
+          assert( aWrite>=pBufStart );                         /* hence (7) */
           memcpy(aSave, aWrite, 4);
           rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
           nextPage = get4byte(aWrite);
diff --git a/test/ovfl.test b/test/ovfl.test
new file mode 100644 (file)
index 0000000..075b1e4
--- /dev/null
@@ -0,0 +1,49 @@
+# 2014 October 01
+#
+# 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 testing the SQLITE_DIRECT_OVERFLOW_READ logic.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix ovfl
+
+# Populate table t2:
+#
+#   CREATE TABLE t1(c1 TEXT, c2 TEXT);
+#
+# with 2000 rows. In each row, c2 spans multiple overflow pages. The text
+# value of c1 ranges in size from 1 to 2000 bytes. The idea is to create
+# at least one row where the first byte of c2 is also the first byte of
+# an overflow page. This was at one point exposing an obscure bug in the
+# SQLITE_DIRECT_OVERFLOW_READ logic.
+#
+do_test 1.1 {
+  set c2 [string repeat abcdefghij 200]
+  execsql {
+    PRAGMA cache_size = 10;
+    CREATE TABLE t1(c1 TEXT, c2 TEXT);
+    BEGIN;
+  }
+  for {set i 1} {$i <= 2000} {incr i} {
+    set c1 [string repeat . $i]
+    execsql { INSERT INTO t1 VALUES($c1, $c2) }
+  }
+  execsql COMMIT
+} {}
+
+do_execsql_test 1.2 {
+  SELECT sum(length(c2)) FROM t1;
+} [expr 2000 * 2000]
+
+finish_test
+
+