SQLite

Check-in [2e85b0e3]
Login

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

Overview
Comment:Fix a crash that could occur in fts5 'secure-delete' mode when operating on corrupt records.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2e85b0e3dcae0915aa6472a3654c8ac72a6b2083c11747f3f657c79bbdaf530b
User & Date: dan 2023-04-29 18:31:44
Context
2023-05-01
11:24
Do not apply the "AND false" optimization if either operand comes from the ON clause of a join. Fix for the problem identified by forum post 96cd4a7e9e. (check-in: d095da0e user: drh tags: trunk)
2023-04-29
18:40
Merge all the latest trunk enhancements into the JSON5 branch to facilitate testing of the JSON5 branch. (check-in: 30d12ede user: drh tags: json5)
18:31
Fix a crash that could occur in fts5 'secure-delete' mode when operating on corrupt records. (check-in: 2e85b0e3 user: dan tags: trunk)
15:42
Cure CLI generate_series() overflow bug (noted by forum post #754e2d4db2a5) and bring behavior with negative step arguments closer to as-documented and eponymous function in PostgreSQL. (check-in: 07383758 user: larrybr tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts5/fts5_index.c.
4629
4630
4631
4632
4633
4634
4635



4636
4637
4638
4639
4640
4641
4642
      ** page and move on to the right-hand peer.  */
      const u8 aEmpty[] = {0x00, 0x00, 0x00, 0x04}; 
      assert_nc( bDetailNone==0 || pLeaf->nn==4 );
      if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty));
      fts5DataRelease(pLeaf);
      pLeaf = 0;
    }else if( bDetailNone ){



      break;
    }else{
      int nShift = iNext - 4;
      int nPg;

      int nIdx = 0;
      u8 *aIdx = 0;







>
>
>







4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
      ** page and move on to the right-hand peer.  */
      const u8 aEmpty[] = {0x00, 0x00, 0x00, 0x04}; 
      assert_nc( bDetailNone==0 || pLeaf->nn==4 );
      if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty));
      fts5DataRelease(pLeaf);
      pLeaf = 0;
    }else if( bDetailNone ){
      break;
    }else if( iNext>=pLeaf->szLeaf || iNext<4 ){
      p->rc = FTS5_CORRUPT;
      break;
    }else{
      int nShift = iNext - 4;
      int nPg;

      int nIdx = 0;
      u8 *aIdx = 0;
Added ext/fts5/test/fts5corrupt7.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 2023 April 30
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt7

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}
sqlite3_fts5_may_be_corrupt 1

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x);
  INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
}

set doc [string repeat "a b " 30]

do_execsql_test 1.1 {
  BEGIN;
    INSERT INTO t1(rowid, x) VALUES(123, $doc);
    INSERT INTO t1(rowid, x) VALUES(124, $doc);
  COMMIT;
}

execsql_pp {
  SELECT id, fts5_decode(id, block), quote(block) FROM t1_data
}

set rows [db eval { SELECT rowid FROM t1_data }]
db_save_and_close

foreach r $rows {
  db_restore_and_reopen

  proc edit_block {b} {
    binary scan $b c* in
    set out [lreplace $in 0 1 255 255]
    binary format c* $out
  }
  db func edit_block edit_block

  do_execsql_test 1.2.$r.1 {
    UPDATE t1_data SET block = edit_block(block) WHERE rowid=$r;
  }

  do_execsql_test 1.2.$r.2 {
    INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
  }

  do_test 1.2.$r.3 {
    catchsql { DELETE FROM t1 WHERE rowid=123; }
    catchsql { DELETE FROM t1 WHERE rowid=124; }
    set {} {}
  } {}

  db close
}

foreach r $rows {
set r 137438953475
  db_restore_and_reopen

  proc edit_block {b} {
    binary scan $b c* in
    set out [lreplace $in end end 127]
    binary format c* $out
  }
  db func edit_block edit_block

  do_execsql_test 1.2.$r.1 {
    UPDATE t1_data SET block = edit_block(block) WHERE rowid=$r;
  }

  do_execsql_test 1.2.$r.2 {
    INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
  }

  do_test 1.2.$r.3 {
    catchsql { DELETE FROM t1 WHERE rowid=124; }
    catchsql { DELETE FROM t1 WHERE rowid=123; }
    set {} {}
  } {}

  db close
}

finish_test