SQLite

Check-in [270d47e8d0]
Login

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

Overview
Comment:Avoid leaking page references when database corruption is encountered. (CVS 5080)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 270d47e8d0a20868879a95b66cb547e1e5b642d9
User & Date: danielk1977 2008-05-05 12:09:33.000
Context
2008-05-05
13:23
Fix a couple of minor problems with transactions in virtual tables. (CVS 5081) (check-in: 2275fc6ee0 user: drh tags: trunk)
12:09
Avoid leaking page references when database corruption is encountered. (CVS 5080) (check-in: 270d47e8d0 user: danielk1977 tags: trunk)
11:33
Fix to test code to build when ENABLE_IOTRACE is not defined. (CVS 5079) (check-in: 8fa2bda4c5 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.453 2008/05/02 14:23:55 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.454 2008/05/05 12:09:33 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

1050
1051
1052
1053
1054
1055
1056




1057
1058
1059
1060
1061
1062
1063
  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT; 
  }
  rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
  if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
    rc = sqlite3BtreeInitPage(*ppPage, pParent);




  }
  return rc;
}

/*
** Release a MemPage.  This should be called once for each prior
** call to sqlite3BtreeGetPage.







>
>
>
>







1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT; 
  }
  rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
  if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
    rc = sqlite3BtreeInitPage(*ppPage, pParent);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
      *ppPage = 0;
    }
  }
  return rc;
}

/*
** Release a MemPage.  This should be called once for each prior
** call to sqlite3BtreeGetPage.
4087
4088
4089
4090
4091
4092
4093
4094

4095
4096
4097
4098
4099
4100
4101
        }

        iPage = get4byte(&aData[8+closest*4]);
        if( !searchList || iPage==nearby ){
          *pPgno = iPage;
          if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){
            /* Free page off the end of the file */
            return SQLITE_CORRUPT_BKPT;

          }
          TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
                 ": %d more free pages\n",
                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
          if( closest<k-1 ){
            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
          }







|
>







4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
        }

        iPage = get4byte(&aData[8+closest*4]);
        if( !searchList || iPage==nearby ){
          *pPgno = iPage;
          if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){
            /* Free page off the end of the file */
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
                 ": %d more free pages\n",
                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
          if( closest<k-1 ){
            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
          }
Changes to test/corrupt.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt.test,v 1.8 2005/02/19 08:18:06 danielk1977 Exp $

catch {file delete -force test.db}
catch {file delete -force test.db-journal}

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








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt.test,v 1.9 2008/05/05 12:09:33 danielk1977 Exp $

catch {file delete -force test.db}
catch {file delete -force test.db-journal}

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

106
107
108
109
110
111
112









113
114
115
116
117
118
119
    catchsql {DROP TABLE t1}
    set x {}
  } {}
  do_test corrupt-2.$tn.7 {
    catchsql {PRAGMA integrity_check}
    set x {}
  } {}









}  

#------------------------------------------------------------------------
# For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an
# index on t1) in sqlite_master. Then perform a few different queries
# and make sure this is detected as corruption.
#







>
>
>
>
>
>
>
>
>







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    catchsql {DROP TABLE t1}
    set x {}
  } {}
  do_test corrupt-2.$tn.7 {
    catchsql {PRAGMA integrity_check}
    set x {}
  } {}

  # Check that no page references were leaked.
  do_test corrupt-2.$tn.8 {
    set bt [btree_from_db db]
    db_enter db
    array set stats [btree_pager_stats $bt]
    db_leave db
    set stats(ref)
  } {0}
}  

#------------------------------------------------------------------------
# For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an
# index on t1) in sqlite_master. Then perform a few different queries
# and make sure this is detected as corruption.
#