/ Check-in [c8e85fff]
Login

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

Overview
Comment:Fix a segfault that could occur while attempting to add new pages to the freelist in a corrupt database. (CVS 4414)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c8e85fff7ede68f0b8c8ebfe3df4b26a630abeff
User & Date: drh 2007-09-07 14:32:07
Context
2007-09-07
18:40
Modify test_thread.c to use tcl apis for creating threads. (CVS 4415) check-in: 9b7bab7f user: danielk1977 tags: trunk
14:32
Fix a segfault that could occur while attempting to add new pages to the freelist in a corrupt database. (CVS 4414) check-in: c8e85fff user: drh tags: trunk
11:29
Add the beginning of the thread-safety tests. There are more to come. (CVS 4413) check-in: 753908e8 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148



4149
4150
4151
4152
4153
4154
4155
** 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.424 2007/09/06 23:39:37 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"

................................................................................
    rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0);
    if( rc ) return rc;
    k = get4byte(&pTrunk->aData[4]);
    if( k>=pBt->usableSize/4 - 8 ){
      /* The trunk is full.  Turn the page being freed into a new
      ** trunk page with no leaves. */
      rc = sqlite3PagerWrite(pPage->pDbPage);
      if( rc ) return rc;
      put4byte(pPage->aData, pTrunk->pgno);
      put4byte(&pPage->aData[4], 0);
      put4byte(&pPage1->aData[32], pPage->pgno);
      TRACE(("FREE-PAGE: %d new trunk page replacing %d\n",
              pPage->pgno, pTrunk->pgno));



    }else{
      /* Add the newly freed page as a leaf on the current trunk */
      rc = sqlite3PagerWrite(pTrunk->pDbPage);
      if( rc==SQLITE_OK ){
        put4byte(&pTrunk->aData[4], k+1);
        put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE







|







 







|
|
|
|
|
|
>
>
>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
** 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.425 2007/09/07 14:32:07 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"

................................................................................
    rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0);
    if( rc ) return rc;
    k = get4byte(&pTrunk->aData[4]);
    if( k>=pBt->usableSize/4 - 8 ){
      /* The trunk is full.  Turn the page being freed into a new
      ** trunk page with no leaves. */
      rc = sqlite3PagerWrite(pPage->pDbPage);
      if( rc==SQLITE_OK ){
        put4byte(pPage->aData, pTrunk->pgno);
        put4byte(&pPage->aData[4], 0);
        put4byte(&pPage1->aData[32], pPage->pgno);
        TRACE(("FREE-PAGE: %d new trunk page replacing %d\n",
                pPage->pgno, pTrunk->pgno));
      }
    }else if( k<0 ){
      rc = SQLITE_CORRUPT;
    }else{
      /* Add the newly freed page as a leaf on the current trunk */
      rc = sqlite3PagerWrite(pTrunk->pDbPage);
      if( rc==SQLITE_OK ){
        put4byte(&pTrunk->aData[4], k+1);
        put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE

Added test/corrupt4.test.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 2007 Sept 7
#
# 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.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $

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

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

# Create a database with a freelist containing at least two pages.
#
do_test corrupt4-1.1 {
  set bigstring [string repeat 0123456789 200]
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=1024;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES($bigstring);
    CREATE TABLE t2(y);
    INSERT INTO t2 VALUES(1);
    DROP TABLE t1;
  }
  file size test.db
} [expr {1024*4}]

# Verify that there are two pages on the freelist.
#
do_test corrupt4-1.2 {
  execsql {PRAGMA freelist_count}
} {2}

# Get the page number for the trunk of the freelist.
#
set trunkpgno [hexio_get_int [hexio_read test.db 32 4]]
set baseaddr [expr {($trunkpgno-1)*1024}]

# Verify that the trunk of the freelist has exactly one
# leaf.
#
do_test corrupt4-1.3 {
  hexio_get_int [hexio_read test.db [expr {$::baseaddr+4}] 4]
} {1}

# Insert a negative number as the number of leaves on the trunk.
# Then try to add a new element to the freelist.
#
do_test corrupt4-1.4 {
  hexio_write test.db [expr {$::baseaddr+4}] [hexio_render_int32 -100000000]
  db close
  sqlite3 db test.db
  catchsql {
    DROP TABLE t2
  }
} {1 {database disk image is malformed}}

finish_test