File: 50-REPLACE_corruption_fix.patch

package info (click to toggle)
sqlite3 3.16.2-5+deb9u1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 88,416 kB
  • sloc: ansic: 195,593; tcl: 14,245; sh: 10,163; yacc: 1,246; makefile: 1,058; cs: 299; cpp: 128
file content (50 lines) | stat: -rw-r--r-- 1,929 bytes parent folder | download
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
Index: sqlite3/src/btree.c
==================================================================
--- sqlite3/src/btree.c
+++ sqlite3/src/btree.c
@@ -8057,16 +8057,22 @@
     oldCell = findCell(pPage, idx);
     if( !pPage->leaf ){
       memcpy(newCell, oldCell, 4);
     }
     rc = clearCell(pPage, oldCell, &info);
-    if( info.nSize==szNew && info.nLocal==info.nPayload ){
+    if( info.nSize==szNew && info.nLocal==info.nPayload 
+     && (!ISAUTOVACUUM || szNew<pPage->minLocal)
+    ){
       /* Overwrite the old cell with the new if they are the same size.
       ** We could also try to do this if the old cell is smaller, then add
       ** the leftover space to the free list.  But experiments show that
       ** doing that is no faster then skipping this optimization and just
-      ** calling dropCell() and insertCell(). */
+      ** calling dropCell() and insertCell(). 
+      **
+      ** This optimization cannot be used on an autovacuum database if the
+      ** new entry uses overflow pages, as the insertCell() call below is
+      ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry.  */
       assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
       if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
       memcpy(oldCell, newCell, szNew);
       return SQLITE_OK;
     }

Index: sqlite3/test/autovacuum.test
==================================================================
--- sqlite3/test/autovacuum.test
+++ sqlite3/test/autovacuum.test
@@ -703,7 +703,14 @@
 do_test autovacuum-9.5 {
   execsql { DELETE FROM t1 WHERE rowid > (SELECT max(a)/2 FROM t1) }
   file size test.db
 } $::sqlite_pending_byte
  
+do_execsql_test autovacuum-10.1 {
+  DROP TABLE t1;
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+  INSERT INTO t1 VALUES(25, randomblob(104));
+  REPLACE INTO t1 VALUES(25, randomblob(1117));
+  PRAGMA integrity_check;
+} {ok}
 
 finish_test