SQLite

Check-in [04925dee]
Login

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

Overview
Comment:Take extra care to avoid an OOB read caused by a corrupt b-tree page. This fixes a problem detected by Natalie Silvanovich of Google Project Zero.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 04925dee41a21ffca9a9f9df27d8165431668c42c2b33d08b077fdb28011170b
User & Date: dan 2017-10-19 15:17:38
Original Comment: Take extra care to avoid an OOB read caused by a corrupt b-tree page.
Context
2017-10-21
13:29
Remove unnecessary "#if SQLITE_MAX_COLUMN". SQLITE_MAX_COLUMN is always defined. (check-in: 6ec82acd user: drh tags: trunk)
12:59
Initial implementation of the appendvfs extension. Untested. (check-in: 063a03a3 user: drh tags: appendvfs)
2017-10-19
15:17
Take extra care to avoid an OOB read caused by a corrupt b-tree page. This fixes a problem detected by Natalie Silvanovich of Google Project Zero. (check-in: 04925dee user: dan tags: trunk)
2017-10-18
15:02
Avoid using snprintf as a member variable of a struct in sqlite3ext.h. This causes problems on OSX. Similar to fix [a1fd3aa8]. (check-in: cd0471ca user: dan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835

4836



4837

4838
4839
4840
4841
4842
4843
4844
4845
** page of the database.  The data might change or move the next time
** any btree routine is called.
*/
static const void *fetchPayload(
  BtCursor *pCur,      /* Cursor pointing to entry to read from */
  u32 *pAmt            /* Write the number of available bytes here */
){
  u32 amt;
  assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
  assert( pCur->eState==CURSOR_VALID );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->ix<pCur->pPage->nCell );
  assert( pCur->info.nSize>0 );
  assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
  assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);

  amt = (int)(pCur->pPage->aDataEnd - pCur->info.pPayload);



  if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal;

  *pAmt = amt;
  return (void*)pCur->info.pPayload;
}


/*
** For the entry that cursor pCur is point to, return as
** many bytes of the key or data as are available on the local







|








>
|
>
>
>
|
>
|







4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
** page of the database.  The data might change or move the next time
** any btree routine is called.
*/
static const void *fetchPayload(
  BtCursor *pCur,      /* Cursor pointing to entry to read from */
  u32 *pAmt            /* Write the number of available bytes here */
){
  int amt;
  assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
  assert( pCur->eState==CURSOR_VALID );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->ix<pCur->pPage->nCell );
  assert( pCur->info.nSize>0 );
  assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
  assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
  amt = pCur->info.nLocal;
  if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
    /* There is too little space on the page for the expected amount
    ** of local content. Database must be corrupt. */
    assert( CORRUPT_DB );
    amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload));
  }
  *pAmt = (u32)amt;
  return (void*)pCur->info.pPayload;
}


/*
** For the entry that cursor pCur is point to, return as
** many bytes of the key or data as are available on the local

Changes to test/corruptK.test.

103
104
105
106
107
108
109













































































































110
111
112
113
  close $fd
} {}

do_catchsql_test 2.3 {
  INSERT INTO t1 VALUES(randomblob(900));
} {1 {database disk image is malformed}}

















































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  close $fd
} {}

do_catchsql_test 2.3 {
  INSERT INTO t1 VALUES(randomblob(900));
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------

proc hex2blob {hex} {
  # Split on newlines:
  set bytes [list]
  foreach l [split $hex "\n"] {
    if {[string is space $l]} continue
    set L [list]
    foreach b [split $l] {
      if {[string is xdigit $b] && [string length $b]==2} { 
        lappend L [expr "0x$b"]
      }
    }
    if {[llength $L]!=16} {
      error "Badly formed hex (1)"
    }
    set bytes [concat $bytes $L]
  }

  binary format c* $bytes
}

reset_db
db func hex2blob hex2blob

do_execsql_test 3.1 {
  PRAGMA page_size=1024;
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(a, b, c);
  CREATE TABLE t3(a, b, c);
  CREATE TABLE t4(a, b, c);
  CREATE TABLE t5(a, b, c);
}

do_execsql_test 3.2 {
  UPDATE sqlite_dbpage SET data = hex2blob('
 000: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
 010: 04 00 01 01 20 40 20 20 00 00 3e d9 00 00 00 06 .... @  ..>.....
 020: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
 030: 0f 00 00 00 00 00 00 00 00 00 00 01 00 00 83 00 ................
 040: 00 00 00 00 00 00 00 00 00 00 00 00 00 38 00 00 .............8..
 050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3e d9 ..............>.
 060: 00 2d e6 07 0d 00 00 00 01 03 a0 00 03 e0 00 00 .-..............
 070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 0a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 0b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 0c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 0d0: 00 00 00 00 00 c1 00 00 00 00 00 00 00 00 00 00 ................
 0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 160: 00 83 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 180: 00 00 00 00 00 00 00 00 00 00 07 00 30 00 00 00 ............0...
 190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 1a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 1c0: 02 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 ................
 1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 1f0: 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 220: 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 230: 0c 00 00 00 00 00 00 60 00 00 00 06 00 00 c3 00 .......`........
 240: 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 270: 00 00 00 18 00 00 00 00 00 00 00 00 00 00 00 00 ................
 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 290: 04 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 2a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 2b0: 00 00 00 00 83 00 8c 00 00 00 00 00 00 00 00 00 ................
 2c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 2d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 2e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 2f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 310: 00 78 00 00 00 00 00 00 00 00 00 00 00 00 70 00 .x............p.
 320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 340: 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 ................
 350: 00 00 00 00 00 68 00 00 00 00 00 00 00 00 00 00 .....h..........
 360: 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 ................
 370: 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 ................
 380: 00 00 00 00 70 00 00 00 00 00 00 00 00 00 00 00 ....p...........
 390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 3a0: 5e 01 07 17 1b 1b 01 81 13 74 61 62 6c 65 73 65 ^........tablese
 3b0: 6e 73 6f 32 73 73 65 6e 73 6f 72 73 02 43 52 45 nso2ssensors.CRE
 3c0: 41 54 45 20 54 41 42 4c 45 20 73 65 6e 73 6f 72 ATE TABLE sensor
 3d0: 73 20 0a 20 20 24 20 20 20 20 20 20 20 20 20 20 s .  $          
 3e0: b8 6e 61 6d 65 21 74 65 78 74 2c 20 79 61 6c 20 .name!text, yal 
 3f0: 72 65 61 6c 2c 20 74 69 6d 65 20 74 65 78 74 29 real, time text)
  ') WHERE pgno=1
}

db close
sqlite3 db test.db

do_catchsql_test 3.3 {
  PRAGMA integrity_check;
} {1 {database disk image is malformed}}



finish_test

Changes to test/permutations.test.

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

test_suite "valgrind" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \
              shell*.test crash8.test atof1.test selectG.test \
              tkt-fc62af4523.test numindex1.test
] -initialize {
  set ::G(valgrind) 1
} -shutdown {
  unset -nocomplain ::G(valgrind)
}

test_suite "valgrind-nolookaside" -prefix "" -description {







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

test_suite "valgrind" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \
              shell*.test crash8.test atof1.test selectG.test \
              tkt-fc62af4523.test numindex1.test corruptK.test
] -initialize {
  set ::G(valgrind) 1
} -shutdown {
  unset -nocomplain ::G(valgrind)
}

test_suite "valgrind-nolookaside" -prefix "" -description {