/ Check-in [2ab14a84]
Login

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

Overview
Comment:Add the SQLITE_DIRECT_OVERFLOW_READ compile time option.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2ab14a846727857175eac7961b7338c4d3b417ca
User & Date: dan 2011-10-08 14:57:07
References
2014-10-01
11:54 New ticket [e3a29096] out-of-bounds write when using non-default malloc implementation and SQLITE_DIRECT_OVERFLOW_READ. artifact: 72fdf842 user: dan
2011-12-21
16:25 New ticket [ac0ff496] Database corruption due to integer overflow with SQLITE_DIRECT_OVERFLOW_READ. artifact: 09f179ff user: drh
Context
2011-10-08
21:39
All the soft_heap_limit to be exceeded by 10% in test cases. check-in: 4be9dccc user: drh tags: trunk
14:57
Add the SQLITE_DIRECT_OVERFLOW_READ compile time option. check-in: 2ab14a84 user: dan tags: trunk
2011-10-07
23:52
Change the ANALYZE command so that it no longer tried to delete unused sqlite_stat2 and sqlite_stat3 tables. Change the DROP TABLE command so that it is able to drop those tables. check-in: 589f3f56 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/btree.c.

3934
3935
3936
3937
3938
3939
3940
3941


3942


































3943
3944
3945
3946
3947
3948
3949
3950
3951
3952


3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
#endif
          rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
        offset -= ovflSize;
      }else{
        /* Need to read this page properly. It contains some of the
        ** range of data that is being read (eOp==0) or written (eOp!=0).
        */
        DbPage *pDbPage;


        int a = amt;


































        rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
        if( rc==SQLITE_OK ){
          aPayload = sqlite3PagerGetData(pDbPage);
          nextPage = get4byte(aPayload);
          if( a + offset > ovflSize ){
            a = ovflSize - offset;
          }
          rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
          sqlite3PagerUnref(pDbPage);
          offset = 0;


          amt -= a;
          pBuf += a;
        }
      }
    }
  }

  if( rc==SQLITE_OK && amt>0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  return rc;
}








|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
<
<
<



>
>





<







3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982



3983
3984
3985
3986
3987
3988
3989
3990
3991
3992

3993
3994
3995
3996
3997
3998
3999
#endif
          rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
        offset -= ovflSize;
      }else{
        /* Need to read this page properly. It contains some of the
        ** range of data that is being read (eOp==0) or written (eOp!=0).
        */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
        sqlite3_file *fd;
#endif
        int a = amt;
        if( a + offset > ovflSize ){
          a = ovflSize - offset;
        }

#ifdef SQLITE_DIRECT_OVERFLOW_READ
        /* If all the following are true:
        **
        **   1) this is a read operation, and 
        **   2) data is required from the start of this overflow page, and
        **   3) the database is file-backed, and
        **   4) there is no open write-transaction, and
        **   5) the database is not a WAL database,
        **
        ** then data can be read directly from the database file into the
        ** output buffer, bypassing the page-cache altogether. This speeds
        ** up loading large records that span many overflow pages.
        */
        if( eOp==0                                             /* (1) */
         && offset==0                                          /* (2) */
         && pBt->inTransaction==TRANS_READ                     /* (4) */
         && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
         && pBt->pPage1->aData[19]==0x01                       /* (5) */
        ){
          u8 aSave[4];
          u8 *aWrite = &pBuf[-4];
          memcpy(aSave, aWrite, 4);
          rc = sqlite3OsRead(fd, aWrite, a+4, pBt->pageSize * (nextPage-1));
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);



            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
          }
        }
        amt -= a;
        pBuf += a;
      }
    }
  }


  if( rc==SQLITE_OK && amt>0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  return rc;
}

Changes to src/test_config.c.

50
51
52
53
54
55
56






57
58
59
60
61
62
63
#endif

#ifdef SQLITE_DEBUG
  Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY);
#endif







#ifdef SQLITE_DISABLE_DIRSYNC
  Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
#endif








>
>
>
>
>
>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#endif

#ifdef SQLITE_DEBUG
  Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_DIRECT_OVERFLOW_READ
  Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "direct_read", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_DISABLE_DIRSYNC
  Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
#endif

Changes to test/corrupt3.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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

# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
  finish_test
  return
}

# Create a database with an overflow page.
#
do_test corrupt3-1.1 {







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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

# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas||direct_read {
  finish_test
  return
}

# Create a database with an overflow page.
#
do_test corrupt3-1.1 {

Changes to test/pager1.test.

1762
1763
1764
1765
1766
1767
1768




1769
1770
1771
1772
1773
1774
1775
....
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
# Test the pagers response to the b-tree layer requesting illegal page 
# numbers:
#
#   + The locking page,
#   + Page 0,
#   + A page with a page number greater than (2^31-1).
#




do_test pager1-18.1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql { 
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(a_string(500), a_string(200));
................................................................................
  set root [db one "SELECT rootpage FROM sqlite_master"]
  db close

  hexio_write test.db [expr ($root-1)*1024 + 8] 00000000
  sqlite3 db test.db
  catchsql { SELECT length(x) FROM t1 }
} {1 {database disk image is malformed}}


do_test pager1-19.1 {
  sqlite3 db ""
  db func a_string a_string
  execsql {
    PRAGMA page_size = 512;
    PRAGMA auto_vacuum = 1;







>
>
>
>







 







>







1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
....
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
# Test the pagers response to the b-tree layer requesting illegal page 
# numbers:
#
#   + The locking page,
#   + Page 0,
#   + A page with a page number greater than (2^31-1).
#
# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In
# that case IO errors are sometimes reported instead of SQLITE_CORRUPT.
#
ifcapable !direct_read {
do_test pager1-18.1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql { 
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(a_string(500), a_string(200));
................................................................................
  set root [db one "SELECT rootpage FROM sqlite_master"]
  db close

  hexio_write test.db [expr ($root-1)*1024 + 8] 00000000
  sqlite3 db test.db
  catchsql { SELECT length(x) FROM t1 }
} {1 {database disk image is malformed}}
}

do_test pager1-19.1 {
  sqlite3 db ""
  db func a_string a_string
  execsql {
    PRAGMA page_size = 512;
    PRAGMA auto_vacuum = 1;

Changes to test/pageropt.test.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# pager optimizations implemented in version 3.3.14 work.
#
# $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {!pager_pragmas||secure_delete} {
  finish_test
  return
}

# Run the SQL statement supplied by the argument and return
# the results.  Prepend four integers to the beginning of the
# result which are







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# pager optimizations implemented in version 3.3.14 work.
#
# $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {!pager_pragmas||secure_delete||direct_read} {
  finish_test
  return
}

# Run the SQL statement supplied by the argument and return
# the results.  Prepend four integers to the beginning of the
# result which are