Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: third_party/sqlite/patches/0023-fts2-Fix-numerous-out-of-bounds-bugs-reading-corrupt.patch

Issue 885473002: [sql] Rewrite sqlite patching "system". (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed typo in readme. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 diff -ru ext-orig/fts2/fts2.c ext/fts2/fts2.c 1 From 106d71238a58d4dfbeb8cf1cba45a1c4e6f583e8 Mon Sep 17 00:00:00 2001
2 --- ext-orig/fts2/fts2.c» 2009-09-04 13:37:41.000000000 -0700 2 From: Chris Evans <cevans@chromium.org>
3 +++ ext/fts2/fts2.c» 2009-09-30 14:48:14.000000000 -0700 3 Date: Wed, 30 Sep 2009 23:10:34 +0000
4 @@ -37,6 +37,20 @@ 4 Subject: [PATCH 23/23] [fts2] Fix numerous out-of-bounds bugs reading corrupt
5 ** This is an SQLite module implementing full-text search. 5 database.
6 */ 6
7 7 Fix numerous bugs in fts2 where a corrupt fts2 database could cause
8 +/* TODO(shess): To make it easier to spot changes without groveling 8 out-of-bounds reads and writes.
9 +** through changelogs, I've defined GEARS_FTS2_CHANGES to call them 9
10 +** out, and I will document them here. On imports, these changes 10 Original review URL is more descriptive:
11 +** should be reviewed to make sure they are still present, or are 11 http://codereview.chromium.org/216026
12 +** dropped as appropriate. 12 ---
13 +** 13 third_party/sqlite/src/ext/fts2/fts2.c | 751 ++++++++++++++++++++++-----------
14 +** SQLite core adds the custom function fts2_tokenizer() to be used 14 1 file changed, 514 insertions(+), 237 deletions(-)
15 +** for defining new tokenizers. The second parameter is a vtable 15
16 +** pointer encoded as a blob. Obviously this cannot be exposed to 16 diff --git a/third_party/sqlite/src/ext/fts2/fts2.c b/third_party/sqlite/src/ext /fts2/fts2.c
17 +** Gears callers for security reasons. It could be suppressed in the 17 index d5587b3..36d14ff 100644
18 +** authorizer, but for now I have simply commented the definition out. 18 --- a/third_party/sqlite/src/ext/fts2/fts2.c
19 +*/ 19 +++ b/third_party/sqlite/src/ext/fts2/fts2.c
20 +#define GEARS_FTS2_CHANGES 1 20 @@ -447,30 +447,41 @@ static int putVarint(char *p, sqlite_int64 v){
21 +
22 /*
23 ** The code in this file is only compiled if:
24 **
25 @@ -326,8 +326,10 @@
26 #include "fts2_hash.h"
27 #include "fts2_tokenizer.h"
28 #include "sqlite3.h"
29 -#include "sqlite3ext.h"
30 -SQLITE_EXTENSION_INIT1
31 +#ifndef SQLITE_CORE
32 +# include "sqlite3ext.h"
33 + SQLITE_EXTENSION_INIT1
34 +#endif
35
36
37 /* TODO(shess) MAN, this thing needs some refactoring. At minimum, it
38 @@ -335,6 +349,16 @@
39 # define TRACE(A)
40 #endif
41
42 +#if 0
43 +/* Useful to set breakpoints. See main.c sqlite3Corrupt(). */
44 +static int fts2Corrupt(void){
45 + return SQLITE_CORRUPT;
46 +}
47 +# define SQLITE_CORRUPT_BKPT fts2Corrupt()
48 +#else
49 +# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
50 +#endif
51 +
52 /* It is not safe to call isspace(), tolower(), or isalnum() on
53 ** hi-bit-set characters. This is the same solution used in the
54 ** tokenizer.
55 @@ -423,30 +447,41 @@
56 /* Read a 64-bit variable-length integer from memory starting at p[0]. 21 /* Read a 64-bit variable-length integer from memory starting at p[0].
57 * Return the number of bytes read, or 0 on error. 22 * Return the number of bytes read, or 0 on error.
58 * The value is stored in *v. */ 23 * The value is stored in *v. */
59 -static int getVarint(const char *p, sqlite_int64 *v){ 24 -static int getVarint(const char *p, sqlite_int64 *v){
60 +static int getVarintSafe(const char *p, sqlite_int64 *v, int max){ 25 +static int getVarintSafe(const char *p, sqlite_int64 *v, int max){
61 const unsigned char *q = (const unsigned char *) p; 26 const unsigned char *q = (const unsigned char *) p;
62 sqlite_uint64 x = 0, y = 1; 27 sqlite_uint64 x = 0, y = 1;
63 - while( (*q & 0x80) == 0x80 ){ 28 - while( (*q & 0x80) == 0x80 ){
64 + if( max>VARINT_MAX ) max = VARINT_MAX; 29 + if( max>VARINT_MAX ) max = VARINT_MAX;
65 + while( max && (*q & 0x80) == 0x80 ){ 30 + while( max && (*q & 0x80) == 0x80 ){
(...skipping 29 matching lines...) Expand all
95 return ret; 60 return ret;
96 } 61 }
97 62
98 +static int getVarint32(const char* p, int *pi){ 63 +static int getVarint32(const char* p, int *pi){
99 + return getVarint32Safe(p, pi, VARINT_MAX); 64 + return getVarint32Safe(p, pi, VARINT_MAX);
100 +} 65 +}
101 + 66 +
102 /*******************************************************************/ 67 /*******************************************************************/
103 /* DataBuffer is used to collect data into a buffer in piecemeal 68 /* DataBuffer is used to collect data into a buffer in piecemeal
104 ** fashion. It implements the usual distinction between amount of 69 ** fashion. It implements the usual distinction between amount of
105 @@ -615,7 +650,7 @@ 70 @@ -639,7 +650,7 @@ typedef struct DLReader {
106 71
107 static int dlrAtEnd(DLReader *pReader){ 72 static int dlrAtEnd(DLReader *pReader){
108 assert( pReader->nData>=0 ); 73 assert( pReader->nData>=0 );
109 - return pReader->nData==0; 74 - return pReader->nData==0;
110 + return pReader->nData<=0; 75 + return pReader->nData<=0;
111 } 76 }
112 static sqlite_int64 dlrDocid(DLReader *pReader){ 77 static sqlite_int64 dlrDocid(DLReader *pReader){
113 assert( !dlrAtEnd(pReader) ); 78 assert( !dlrAtEnd(pReader) );
114 @@ -639,7 +674,8 @@ 79 @@ -663,7 +674,8 @@ static int dlrAllDataBytes(DLReader *pReader){
115 */ 80 */
116 static const char *dlrPosData(DLReader *pReader){ 81 static const char *dlrPosData(DLReader *pReader){
117 sqlite_int64 iDummy; 82 sqlite_int64 iDummy;
118 - int n = getVarint(pReader->pData, &iDummy); 83 - int n = getVarint(pReader->pData, &iDummy);
119 + int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement); 84 + int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement);
120 + if( !n ) return NULL; 85 + if( !n ) return NULL;
121 assert( !dlrAtEnd(pReader) ); 86 assert( !dlrAtEnd(pReader) );
122 return pReader->pData+n; 87 return pReader->pData+n;
123 } 88 }
124 @@ -649,7 +685,7 @@ 89 @@ -673,7 +685,7 @@ static int dlrPosDataLen(DLReader *pReader){
125 assert( !dlrAtEnd(pReader) ); 90 assert( !dlrAtEnd(pReader) );
126 return pReader->nElement-n; 91 return pReader->nElement-n;
127 } 92 }
128 -static void dlrStep(DLReader *pReader){ 93 -static void dlrStep(DLReader *pReader){
129 +static int dlrStep(DLReader *pReader){ 94 +static int dlrStep(DLReader *pReader){
130 assert( !dlrAtEnd(pReader) ); 95 assert( !dlrAtEnd(pReader) );
131 96
132 /* Skip past current doclist element. */ 97 /* Skip past current doclist element. */
133 @@ -658,32 +694,48 @@ 98 @@ -682,32 +694,48 @@ static void dlrStep(DLReader *pReader){
134 pReader->nData -= pReader->nElement; 99 pReader->nData -= pReader->nElement;
135 100
136 /* If there is more data, read the next doclist element. */ 101 /* If there is more data, read the next doclist element. */
137 - if( pReader->nData!=0 ){ 102 - if( pReader->nData!=0 ){
138 + if( pReader->nData>0 ){ 103 + if( pReader->nData>0 ){
139 sqlite_int64 iDocidDelta; 104 sqlite_int64 iDocidDelta;
140 - int iDummy, n = getVarint(pReader->pData, &iDocidDelta); 105 - int iDummy, n = getVarint(pReader->pData, &iDocidDelta);
141 + int nTotal = 0; 106 + int nTotal = 0;
142 + int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData) ; 107 + int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData) ;
143 + if( !n ) return SQLITE_CORRUPT_BKPT; 108 + if( !n ) return SQLITE_CORRUPT_BKPT;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 - const char *pData, int nData){ 150 - const char *pData, int nData){
186 +static void dlrDestroy(DLReader *pReader){ 151 +static void dlrDestroy(DLReader *pReader){
187 + SCRAMBLE(pReader); 152 + SCRAMBLE(pReader);
188 +} 153 +}
189 +static int dlrInit(DLReader *pReader, DocListType iType, 154 +static int dlrInit(DLReader *pReader, DocListType iType,
190 + const char *pData, int nData){ 155 + const char *pData, int nData){
191 + int rc; 156 + int rc;
192 assert( pData!=NULL && nData!=0 ); 157 assert( pData!=NULL && nData!=0 );
193 pReader->iType = iType; 158 pReader->iType = iType;
194 pReader->pData = pData; 159 pReader->pData = pData;
195 @@ -692,10 +744,9 @@ 160 @@ -716,10 +744,9 @@ static void dlrInit(DLReader *pReader, DocListType iType,
196 pReader->iDocid = 0; 161 pReader->iDocid = 0;
197 162
198 /* Load the first element's data. There must be a first element. */ 163 /* Load the first element's data. There must be a first element. */
199 - dlrStep(pReader); 164 - dlrStep(pReader);
200 -} 165 -}
201 -static void dlrDestroy(DLReader *pReader){ 166 -static void dlrDestroy(DLReader *pReader){
202 - SCRAMBLE(pReader); 167 - SCRAMBLE(pReader);
203 + rc = dlrStep(pReader); 168 + rc = dlrStep(pReader);
204 + if( rc!=SQLITE_OK ) dlrDestroy(pReader); 169 + if( rc!=SQLITE_OK ) dlrDestroy(pReader);
205 + return rc; 170 + return rc;
206 } 171 }
207 172
208 #ifndef NDEBUG 173 #ifndef NDEBUG
209 @@ -782,9 +833,9 @@ 174 @@ -806,9 +833,9 @@ static void dlwDestroy(DLWriter *pWriter){
210 /* TODO(shess) This has become just a helper for docListMerge. 175 /* TODO(shess) This has become just a helper for docListMerge.
211 ** Consider a refactor to make this cleaner. 176 ** Consider a refactor to make this cleaner.
212 */ 177 */
213 -static void dlwAppend(DLWriter *pWriter, 178 -static void dlwAppend(DLWriter *pWriter,
214 - const char *pData, int nData, 179 - const char *pData, int nData,
215 - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ 180 - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
216 +static int dlwAppend(DLWriter *pWriter, 181 +static int dlwAppend(DLWriter *pWriter,
217 + const char *pData, int nData, 182 + const char *pData, int nData,
218 + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ 183 + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
219 sqlite_int64 iDocid = 0; 184 sqlite_int64 iDocid = 0;
220 char c[VARINT_MAX]; 185 char c[VARINT_MAX];
221 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ 186 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */
222 @@ -793,7 +844,8 @@ 187 @@ -817,7 +844,8 @@ static void dlwAppend(DLWriter *pWriter,
223 #endif 188 #endif
224 189
225 /* Recode the initial docid as delta from iPrevDocid. */ 190 /* Recode the initial docid as delta from iPrevDocid. */
226 - nFirstOld = getVarint(pData, &iDocid); 191 - nFirstOld = getVarint(pData, &iDocid);
227 + nFirstOld = getVarintSafe(pData, &iDocid, nData); 192 + nFirstOld = getVarintSafe(pData, &iDocid, nData);
228 + if( !nFirstOld ) return SQLITE_CORRUPT_BKPT; 193 + if( !nFirstOld ) return SQLITE_CORRUPT_BKPT;
229 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) ); 194 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
230 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid); 195 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);
231 196
232 @@ -814,10 +866,11 @@ 197 @@ -838,10 +866,11 @@ static void dlwAppend(DLWriter *pWriter,
233 dataBufferAppend(pWriter->b, c, nFirstNew); 198 dataBufferAppend(pWriter->b, c, nFirstNew);
234 } 199 }
235 pWriter->iPrevDocid = iLastDocid; 200 pWriter->iPrevDocid = iLastDocid;
236 + return SQLITE_OK; 201 + return SQLITE_OK;
237 } 202 }
238 -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ 203 -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){
239 - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), 204 - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
240 - dlrDocid(pReader), dlrDocid(pReader)); 205 - dlrDocid(pReader), dlrDocid(pReader));
241 +static int dlwCopy(DLWriter *pWriter, DLReader *pReader){ 206 +static int dlwCopy(DLWriter *pWriter, DLReader *pReader){
242 + return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), 207 + return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
243 + dlrDocid(pReader), dlrDocid(pReader)); 208 + dlrDocid(pReader), dlrDocid(pReader));
244 } 209 }
245 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ 210 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
246 char c[VARINT_MAX]; 211 char c[VARINT_MAX];
247 @@ -878,45 +931,63 @@ 212 @@ -902,45 +931,63 @@ static int plrEndOffset(PLReader *pReader){
248 assert( !plrAtEnd(pReader) ); 213 assert( !plrAtEnd(pReader) );
249 return pReader->iEndOffset; 214 return pReader->iEndOffset;
250 } 215 }
251 -static void plrStep(PLReader *pReader){ 216 -static void plrStep(PLReader *pReader){
252 - int i, n; 217 - int i, n;
253 +static int plrStep(PLReader *pReader){ 218 +static int plrStep(PLReader *pReader){
254 + int i, n, nTotal = 0; 219 + int i, n, nTotal = 0;
255 220
256 assert( !plrAtEnd(pReader) ); 221 assert( !plrAtEnd(pReader) );
257 222
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 -static void plrInit(PLReader *pReader, DLReader *pDLReader){ 280 -static void plrInit(PLReader *pReader, DLReader *pDLReader){
316 +static void plrDestroy(PLReader *pReader){ 281 +static void plrDestroy(PLReader *pReader){
317 + SCRAMBLE(pReader); 282 + SCRAMBLE(pReader);
318 +} 283 +}
319 + 284 +
320 +static int plrInit(PLReader *pReader, DLReader *pDLReader){ 285 +static int plrInit(PLReader *pReader, DLReader *pDLReader){
321 + int rc; 286 + int rc;
322 pReader->pData = dlrPosData(pDLReader); 287 pReader->pData = dlrPosData(pDLReader);
323 pReader->nData = dlrPosDataLen(pDLReader); 288 pReader->nData = dlrPosDataLen(pDLReader);
324 pReader->iType = pDLReader->iType; 289 pReader->iType = pDLReader->iType;
325 @@ -924,10 +995,9 @@ 290 @@ -948,10 +995,9 @@ static void plrInit(PLReader *pReader, DLReader *pDLReader) {
326 pReader->iPosition = 0; 291 pReader->iPosition = 0;
327 pReader->iStartOffset = 0; 292 pReader->iStartOffset = 0;
328 pReader->iEndOffset = 0; 293 pReader->iEndOffset = 0;
329 - plrStep(pReader); 294 - plrStep(pReader);
330 -} 295 -}
331 -static void plrDestroy(PLReader *pReader){ 296 -static void plrDestroy(PLReader *pReader){
332 - SCRAMBLE(pReader); 297 - SCRAMBLE(pReader);
333 + rc = plrStep(pReader); 298 + rc = plrStep(pReader);
334 + if( rc!=SQLITE_OK ) plrDestroy(pReader); 299 + if( rc!=SQLITE_OK ) plrDestroy(pReader);
335 + return rc; 300 + return rc;
336 } 301 }
337 302
338 /*******************************************************************/ 303 /*******************************************************************/
339 @@ -1113,14 +1183,16 @@ 304 @@ -1137,14 +1183,16 @@ static void dlcDelete(DLCollector *pCollector){
340 ** deletion will be trimmed, and will thus not effect a deletion 305 ** deletion will be trimmed, and will thus not effect a deletion
341 ** during the merge. 306 ** during the merge.
342 */ 307 */
343 -static void docListTrim(DocListType iType, const char *pData, int nData, 308 -static void docListTrim(DocListType iType, const char *pData, int nData,
344 - int iColumn, DocListType iOutType, DataBuffer *out){ 309 - int iColumn, DocListType iOutType, DataBuffer *out){
345 +static int docListTrim(DocListType iType, const char *pData, int nData, 310 +static int docListTrim(DocListType iType, const char *pData, int nData,
346 + int iColumn, DocListType iOutType, DataBuffer *out){ 311 + int iColumn, DocListType iOutType, DataBuffer *out){
347 DLReader dlReader; 312 DLReader dlReader;
348 DLWriter dlWriter; 313 DLWriter dlWriter;
349 + int rc; 314 + int rc;
350 315
351 assert( iOutType<=iType ); 316 assert( iOutType<=iType );
352 317
353 - dlrInit(&dlReader, iType, pData, nData); 318 - dlrInit(&dlReader, iType, pData, nData);
354 + rc = dlrInit(&dlReader, iType, pData, nData); 319 + rc = dlrInit(&dlReader, iType, pData, nData);
355 + if( rc!=SQLITE_OK ) return rc; 320 + if( rc!=SQLITE_OK ) return rc;
356 dlwInit(&dlWriter, iOutType, out); 321 dlwInit(&dlWriter, iOutType, out);
357 322
358 while( !dlrAtEnd(&dlReader) ){ 323 while( !dlrAtEnd(&dlReader) ){
359 @@ -1128,7 +1200,8 @@ 324 @@ -1152,7 +1200,8 @@ static void docListTrim(DocListType iType, const char *pDa ta, int nData,
360 PLWriter plWriter; 325 PLWriter plWriter;
361 int match = 0; 326 int match = 0;
362 327
363 - plrInit(&plReader, &dlReader); 328 - plrInit(&plReader, &dlReader);
364 + rc = plrInit(&plReader, &dlReader); 329 + rc = plrInit(&plReader, &dlReader);
365 + if( rc!=SQLITE_OK ) break; 330 + if( rc!=SQLITE_OK ) break;
366 331
367 while( !plrAtEnd(&plReader) ){ 332 while( !plrAtEnd(&plReader) ){
368 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ 333 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
369 @@ -1139,7 +1212,11 @@ 334 @@ -1163,7 +1212,11 @@ static void docListTrim(DocListType iType, const char *pD ata, int nData,
370 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), 335 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
371 plrStartOffset(&plReader), plrEndOffset(&plReader)); 336 plrStartOffset(&plReader), plrEndOffset(&plReader));
372 } 337 }
373 - plrStep(&plReader); 338 - plrStep(&plReader);
374 + rc = plrStep(&plReader); 339 + rc = plrStep(&plReader);
375 + if( rc!=SQLITE_OK ){ 340 + if( rc!=SQLITE_OK ){
376 + plrDestroy(&plReader); 341 + plrDestroy(&plReader);
377 + goto err; 342 + goto err;
378 + } 343 + }
379 } 344 }
380 if( match ){ 345 if( match ){
381 plwTerminate(&plWriter); 346 plwTerminate(&plWriter);
382 @@ -1147,10 +1224,13 @@ 347 @@ -1171,10 +1224,13 @@ static void docListTrim(DocListType iType, const char *p Data, int nData,
383 } 348 }
384 349
385 plrDestroy(&plReader); 350 plrDestroy(&plReader);
386 - dlrStep(&dlReader); 351 - dlrStep(&dlReader);
387 + rc = dlrStep(&dlReader); 352 + rc = dlrStep(&dlReader);
388 + if( rc!=SQLITE_OK ) break; 353 + if( rc!=SQLITE_OK ) break;
389 } 354 }
390 +err: 355 +err:
391 dlwDestroy(&dlWriter); 356 dlwDestroy(&dlWriter);
392 dlrDestroy(&dlReader); 357 dlrDestroy(&dlReader);
393 + return rc; 358 + return rc;
394 } 359 }
395 360
396 /* Used by docListMerge() to keep doclists in the ascending order by 361 /* Used by docListMerge() to keep doclists in the ascending order by
397 @@ -1207,19 +1287,20 @@ 362 @@ -1231,19 +1287,20 @@ static void orderedDLReaderReorder(OrderedDLReader *p, i nt n){
398 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably 363 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably
399 ** be fixed. 364 ** be fixed.
400 */ 365 */
401 -static void docListMerge(DataBuffer *out, 366 -static void docListMerge(DataBuffer *out,
402 - DLReader *pReaders, int nReaders){ 367 - DLReader *pReaders, int nReaders){
403 +static int docListMerge(DataBuffer *out, 368 +static int docListMerge(DataBuffer *out,
404 + DLReader *pReaders, int nReaders){ 369 + DLReader *pReaders, int nReaders){
405 OrderedDLReader readers[MERGE_COUNT]; 370 OrderedDLReader readers[MERGE_COUNT];
406 DLWriter writer; 371 DLWriter writer;
407 int i, n; 372 int i, n;
408 const char *pStart = 0; 373 const char *pStart = 0;
409 int nStart = 0; 374 int nStart = 0;
410 sqlite_int64 iFirstDocid = 0, iLastDocid = 0; 375 sqlite_int64 iFirstDocid = 0, iLastDocid = 0;
411 + int rc = SQLITE_OK; 376 + int rc = SQLITE_OK;
412 377
413 assert( nReaders>0 ); 378 assert( nReaders>0 );
414 if( nReaders==1 ){ 379 if( nReaders==1 ){
415 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); 380 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
416 - return; 381 - return;
417 + return SQLITE_OK; 382 + return SQLITE_OK;
418 } 383 }
419 384
420 assert( nReaders<=MERGE_COUNT ); 385 assert( nReaders<=MERGE_COUNT );
421 @@ -1252,20 +1333,23 @@ 386 @@ -1276,20 +1333,23 @@ static void docListMerge(DataBuffer *out,
422 nStart += dlrDocDataBytes(readers[0].pReader); 387 nStart += dlrDocDataBytes(readers[0].pReader);
423 }else{ 388 }else{
424 if( pStart!=0 ){ 389 if( pStart!=0 ){
425 - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 390 - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
426 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 391 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
427 + if( rc!=SQLITE_OK ) goto err; 392 + if( rc!=SQLITE_OK ) goto err;
428 } 393 }
429 pStart = dlrDocData(readers[0].pReader); 394 pStart = dlrDocData(readers[0].pReader);
430 nStart = dlrDocDataBytes(readers[0].pReader); 395 nStart = dlrDocDataBytes(readers[0].pReader);
431 iFirstDocid = iDocid; 396 iFirstDocid = iDocid;
432 } 397 }
433 iLastDocid = iDocid; 398 iLastDocid = iDocid;
434 - dlrStep(readers[0].pReader); 399 - dlrStep(readers[0].pReader);
435 + rc = dlrStep(readers[0].pReader); 400 + rc = dlrStep(readers[0].pReader);
436 + if( rc!=SQLITE_OK ) goto err; 401 + if( rc!=SQLITE_OK ) goto err;
437 402
438 /* Drop all of the older elements with the same docid. */ 403 /* Drop all of the older elements with the same docid. */
439 for(i=1; i<nReaders && 404 for(i=1; i<nReaders &&
440 !dlrAtEnd(readers[i].pReader) && 405 !dlrAtEnd(readers[i].pReader) &&
441 dlrDocid(readers[i].pReader)==iDocid; i++){ 406 dlrDocid(readers[i].pReader)==iDocid; i++){
442 - dlrStep(readers[i].pReader); 407 - dlrStep(readers[i].pReader);
443 + rc = dlrStep(readers[i].pReader); 408 + rc = dlrStep(readers[i].pReader);
444 + if( rc!=SQLITE_OK ) goto err; 409 + if( rc!=SQLITE_OK ) goto err;
445 } 410 }
446 411
447 /* Get the readers back into order. */ 412 /* Get the readers back into order. */
448 @@ -1275,8 +1359,11 @@ 413 @@ -1299,8 +1359,11 @@ static void docListMerge(DataBuffer *out,
449 } 414 }
450 415
451 /* Copy over any remaining elements. */ 416 /* Copy over any remaining elements. */
452 - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 417 - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
453 + if( nStart>0 ) 418 + if( nStart>0 )
454 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 419 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
455 +err: 420 +err:
456 dlwDestroy(&writer); 421 dlwDestroy(&writer);
457 + return rc; 422 + return rc;
458 } 423 }
459 424
460 /* Helper function for posListUnion(). Compares the current position 425 /* Helper function for posListUnion(). Compares the current position
461 @@ -1312,30 +1399,40 @@ 426 @@ -1336,30 +1399,40 @@ static int posListCmp(PLReader *pLeft, PLReader *pRight) {
462 ** work with any doclist type, though both inputs and the output 427 ** work with any doclist type, though both inputs and the output
463 ** should be the same type. 428 ** should be the same type.
464 */ 429 */
465 -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ 430 -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
466 +static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ 431 +static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
467 PLReader left, right; 432 PLReader left, right;
468 PLWriter writer; 433 PLWriter writer;
469 + int rc; 434 + int rc;
470 435
471 assert( dlrDocid(pLeft)==dlrDocid(pRight) ); 436 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
(...skipping 27 matching lines...) Expand all
499 plwCopy(&writer, &left); 464 plwCopy(&writer, &left);
500 - plrStep(&left); 465 - plrStep(&left);
501 - plrStep(&right); 466 - plrStep(&right);
502 + rc = plrStep(&left); 467 + rc = plrStep(&left);
503 + if( rc != SQLITE_OK ) break; 468 + if( rc != SQLITE_OK ) break;
504 + rc = plrStep(&right); 469 + rc = plrStep(&right);
505 + if( rc != SQLITE_OK ) break; 470 + if( rc != SQLITE_OK ) break;
506 } 471 }
507 } 472 }
508 473
509 @@ -1343,56 +1440,75 @@ 474 @@ -1367,56 +1440,75 @@ static void posListUnion(DLReader *pLeft, DLReader *pRig ht, DLWriter *pOut){
510 plwDestroy(&writer); 475 plwDestroy(&writer);
511 plrDestroy(&left); 476 plrDestroy(&left);
512 plrDestroy(&right); 477 plrDestroy(&right);
513 + return rc; 478 + return rc;
514 } 479 }
515 480
516 /* Write the union of doclists in pLeft and pRight to pOut. For 481 /* Write the union of doclists in pLeft and pRight to pOut. For
517 ** docids in common between the inputs, the union of the position 482 ** docids in common between the inputs, the union of the position
518 ** lists is written. Inputs and outputs are always type DL_DEFAULT. 483 ** lists is written. Inputs and outputs are always type DL_DEFAULT.
519 */ 484 */
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 } 556 }
592 } 557 }
593 558
594 dlrDestroy(&left); 559 dlrDestroy(&left);
595 dlrDestroy(&right); 560 dlrDestroy(&right);
596 dlwDestroy(&writer); 561 dlwDestroy(&writer);
597 + return rc; 562 + return rc;
598 } 563 }
599 564
600 /* pLeft and pRight are DLReaders positioned to the same docid. 565 /* pLeft and pRight are DLReaders positioned to the same docid.
601 @@ -1407,35 +1523,47 @@ 566 @@ -1431,35 +1523,47 @@ static void docListUnion(
602 ** include the positions from pRight that are one more than a 567 ** include the positions from pRight that are one more than a
603 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1. 568 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
604 */ 569 */
605 -static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight, 570 -static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
606 - DLWriter *pOut){ 571 - DLWriter *pOut){
607 +static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight, 572 +static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
608 + DLWriter *pOut){ 573 + DLWriter *pOut){
609 PLReader left, right; 574 PLReader left, right;
610 PLWriter writer; 575 PLWriter writer;
611 int match = 0; 576 int match = 0;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); 614 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
650 - plrStep(&left); 615 - plrStep(&left);
651 - plrStep(&right); 616 - plrStep(&right);
652 + rc = plrStep(&left); 617 + rc = plrStep(&left);
653 + if( rc!=SQLITE_OK ) break; 618 + if( rc!=SQLITE_OK ) break;
654 + rc = plrStep(&right); 619 + rc = plrStep(&right);
655 + if( rc!=SQLITE_OK ) break; 620 + if( rc!=SQLITE_OK ) break;
656 } 621 }
657 } 622 }
658 623
659 @@ -1446,6 +1574,7 @@ 624 @@ -1470,6 +1574,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader * pRight,
660 625
661 plrDestroy(&left); 626 plrDestroy(&left);
662 plrDestroy(&right); 627 plrDestroy(&right);
663 + return rc; 628 + return rc;
664 } 629 }
665 630
666 /* We have two doclists with positions: pLeft and pRight. 631 /* We have two doclists with positions: pLeft and pRight.
667 @@ -1457,7 +1586,7 @@ 632 @@ -1481,7 +1586,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader * pRight,
668 ** iType controls the type of data written to pOut. If iType is 633 ** iType controls the type of data written to pOut. If iType is
669 ** DL_POSITIONS, the positions are those from pRight. 634 ** DL_POSITIONS, the positions are those from pRight.
670 */ 635 */
671 -static void docListPhraseMerge( 636 -static void docListPhraseMerge(
672 +static int docListPhraseMerge( 637 +static int docListPhraseMerge(
673 const char *pLeft, int nLeft, 638 const char *pLeft, int nLeft,
674 const char *pRight, int nRight, 639 const char *pRight, int nRight,
675 DocListType iType, 640 DocListType iType,
676 @@ -1465,152 +1594,198 @@ 641 @@ -1489,152 +1594,198 @@ static void docListPhraseMerge(
677 ){ 642 ){
678 DLReader left, right; 643 DLReader left, right;
679 DLWriter writer; 644 DLWriter writer;
680 + int rc; 645 + int rc;
681 646
682 - if( nLeft==0 || nRight==0 ) return; 647 - if( nLeft==0 || nRight==0 ) return;
683 + if( nLeft==0 || nRight==0 ) return SQLITE_OK; 648 + if( nLeft==0 || nRight==0 ) return SQLITE_OK;
684 649
685 assert( iType!=DL_POSITIONS_OFFSETS ); 650 assert( iType!=DL_POSITIONS_OFFSETS );
686 651
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 } 864 }
900 865
901 +err: 866 +err:
902 dlrDestroy(&left); 867 dlrDestroy(&left);
903 dlrDestroy(&right); 868 dlrDestroy(&right);
904 dlwDestroy(&writer); 869 dlwDestroy(&writer);
905 + return rc; 870 + return rc;
906 } 871 }
907 872
908 static char *string_dup_n(const char *s, int n){ 873 static char *string_dup_n(const char *s, int n){
909 @@ -1814,7 +1989,7 @@ 874 @@ -3437,7 +3588,8 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){
910 /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?",
911 /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)",
912 /* SEGDIR_SELECT_LEVEL */
913 - "select start_block, leaves_end_block, root from %_segdir "
914 + "select start_block, leaves_end_block, root, idx from %_segdir "
915 " where level = ? order by idx",
916 /* SEGDIR_SPAN */
917 "select min(start_block), max(end_block) from %_segdir "
918 @@ -3413,7 +3588,8 @@
919 return SQLITE_OK; 875 return SQLITE_OK;
920 } 876 }
921 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); 877 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
922 - dlrStep(&c->reader); 878 - dlrStep(&c->reader);
923 + if( rc!=SQLITE_OK ) return rc; 879 + if( rc!=SQLITE_OK ) return rc;
924 + rc = dlrStep(&c->reader); 880 + rc = dlrStep(&c->reader);
925 if( rc!=SQLITE_OK ) return rc; 881 if( rc!=SQLITE_OK ) return rc;
926 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ 882 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
927 rc = sqlite3_step(c->pStmt); 883 rc = sqlite3_step(c->pStmt);
928 @@ -3421,8 +3597,11 @@ 884 @@ -3497,14 +3649,18 @@ static int docListOfTerm(
929 c->eof = 0;
930 return SQLITE_OK;
931 }
932 - /* an error occurred; abort */
933 - return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
934 +
935 + /* Corrupt if the index refers to missing document. */
936 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
937 +
938 + return rc;
939 }
940 }
941
942 @@ -3470,14 +3649,18 @@
943 return rc; 885 return rc;
944 } 886 }
945 dataBufferInit(&new, 0); 887 dataBufferInit(&new, 0);
946 - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, 888 - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
947 - i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new); 889 - i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
948 + rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, 890 + rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
949 + i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new) ; 891 + i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new) ;
950 dataBufferDestroy(&left); 892 dataBufferDestroy(&left);
951 dataBufferDestroy(&right); 893 dataBufferDestroy(&right);
952 + if( rc!=SQLITE_OK ){ 894 + if( rc!=SQLITE_OK ){
953 + dataBufferDestroy(&new); 895 + dataBufferDestroy(&new);
954 + return rc; 896 + return rc;
955 + } 897 + }
956 left = new; 898 left = new;
957 } 899 }
958 *pResult = left; 900 *pResult = left;
959 - return SQLITE_OK; 901 - return SQLITE_OK;
960 + return rc; 902 + return rc;
961 } 903 }
962 904
963 /* Add a new term pTerm[0..nTerm-1] to the query *q. 905 /* Add a new term pTerm[0..nTerm-1] to the query *q.
964 @@ -3544,6 +3727,7 @@ 906 @@ -3749,18 +3905,30 @@ static int fulltextQuery(
965 int firstIndex = pQuery->nTerms;
966 int iCol;
967 int nTerm = 1;
968 + int iEndLast = -1;
969
970 int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
971 if( rc!=SQLITE_OK ) return rc;
972 @@ -3568,6 +3752,20 @@
973 pQuery->nextIsOr = 1;
974 continue;
975 }
976 +
977 + /*
978 + * The ICU tokenizer considers '*' a break character, so the code below
979 + * sets isPrefix correctly, but since that code doesn't eat the '*', the
980 + * ICU tokenizer returns it as the next token. So eat it here until a
981 + * better solution presents itself.
982 + */
983 + if( pQuery->nTerms>0 && nToken==1 && pSegment[iBegin]=='*' &&
984 + iEndLast==iBegin){
985 + pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
986 + continue;
987 + }
988 + iEndLast = iEnd;
989 +
990 queryAdd(pQuery, pToken, nToken);
991 if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
992 pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
993 @@ -3707,18 +3905,30 @@
994 return rc; 907 return rc;
995 } 908 }
996 dataBufferInit(&new, 0); 909 dataBufferInit(&new, 0);
997 - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); 910 - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
998 + rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); 911 + rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
999 dataBufferDestroy(&right); 912 dataBufferDestroy(&right);
1000 dataBufferDestroy(&or); 913 dataBufferDestroy(&or);
1001 + if( rc!=SQLITE_OK ){ 914 + if( rc!=SQLITE_OK ){
1002 + if( i!=nNot ) dataBufferDestroy(&left); 915 + if( i!=nNot ) dataBufferDestroy(&left);
1003 + queryClear(pQuery); 916 + queryClear(pQuery);
(...skipping 12 matching lines...) Expand all
1016 dataBufferDestroy(&right); 929 dataBufferDestroy(&right);
1017 dataBufferDestroy(&left); 930 dataBufferDestroy(&left);
1018 + if( rc!=SQLITE_OK ){ 931 + if( rc!=SQLITE_OK ){
1019 + queryClear(pQuery); 932 + queryClear(pQuery);
1020 + dataBufferDestroy(&new); 933 + dataBufferDestroy(&new);
1021 + return rc; 934 + return rc;
1022 + } 935 + }
1023 left = new; 936 left = new;
1024 } 937 }
1025 } 938 }
1026 @@ -3738,9 +3948,15 @@ 939 @@ -3780,9 +3948,15 @@ static int fulltextQuery(
1027 return rc; 940 return rc;
1028 } 941 }
1029 dataBufferInit(&new, 0); 942 dataBufferInit(&new, 0);
1030 - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); 943 - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new);
1031 + rc = docListExceptMerge(left.pData, left.nData, 944 + rc = docListExceptMerge(left.pData, left.nData,
1032 + right.pData, right.nData, &new); 945 + right.pData, right.nData, &new);
1033 dataBufferDestroy(&right); 946 dataBufferDestroy(&right);
1034 dataBufferDestroy(&left); 947 dataBufferDestroy(&left);
1035 + if( rc!=SQLITE_OK ){ 948 + if( rc!=SQLITE_OK ){
1036 + queryClear(pQuery); 949 + queryClear(pQuery);
1037 + dataBufferDestroy(&new); 950 + dataBufferDestroy(&new);
1038 + return rc; 951 + return rc;
1039 + } 952 + }
1040 left = new; 953 left = new;
1041 } 954 }
1042 955
1043 @@ -3834,7 +4050,8 @@ 956 @@ -3876,7 +4050,8 @@ static int fulltextFilter(
1044 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c-> q); 957 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c-> q);
1045 if( rc!=SQLITE_OK ) return rc; 958 if( rc!=SQLITE_OK ) return rc;
1046 if( c->result.nData!=0 ){ 959 if( c->result.nData!=0 ){
1047 - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); 960 - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
1048 + rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); 961 + rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
1049 + if( rc!=SQLITE_OK ) return rc; 962 + if( rc!=SQLITE_OK ) return rc;
1050 } 963 }
1051 break; 964 break;
1052 } 965 }
1053 @@ -4335,22 +4552,19 @@ 966 @@ -4377,22 +4552,19 @@ static void interiorReaderDestroy(InteriorReader *pReade r){
1054 SCRAMBLE(pReader); 967 SCRAMBLE(pReader);
1055 } 968 }
1056 969
1057 -/* TODO(shess) The assertions are great, but what if we're in NDEBUG 970 -/* TODO(shess) The assertions are great, but what if we're in NDEBUG
1058 -** and the blob is empty or otherwise contains suspect data? 971 -** and the blob is empty or otherwise contains suspect data?
1059 -*/ 972 -*/
1060 -static void interiorReaderInit(const char *pData, int nData, 973 -static void interiorReaderInit(const char *pData, int nData,
1061 - InteriorReader *pReader){ 974 - InteriorReader *pReader){
1062 +static int interiorReaderInit(const char *pData, int nData, 975 +static int interiorReaderInit(const char *pData, int nData,
1063 + InteriorReader *pReader){ 976 + InteriorReader *pReader){
1064 int n, nTerm; 977 int n, nTerm;
1065 978
1066 - /* Require at least the leading flag byte */ 979 - /* Require at least the leading flag byte */
1067 + /* These conditions are checked and met by the callers. */ 980 + /* These conditions are checked and met by the callers. */
1068 assert( nData>0 ); 981 assert( nData>0 );
1069 assert( pData[0]!='\0' ); 982 assert( pData[0]!='\0' );
1070 983
1071 CLEAR(pReader); 984 CLEAR(pReader);
1072 985
1073 /* Decode the base blockid, and set the cursor to the first term. */ 986 /* Decode the base blockid, and set the cursor to the first term. */
1074 - n = getVarint(pData+1, &pReader->iBlockid); 987 - n = getVarint(pData+1, &pReader->iBlockid);
1075 - assert( 1+n<=nData ); 988 - assert( 1+n<=nData );
1076 + n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1); 989 + n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1);
1077 + if( !n ) return SQLITE_CORRUPT_BKPT; 990 + if( !n ) return SQLITE_CORRUPT_BKPT;
1078 pReader->pData = pData+1+n; 991 pReader->pData = pData+1+n;
1079 pReader->nData = nData-(1+n); 992 pReader->nData = nData-(1+n);
1080 993
1081 @@ -4361,17 +4575,18 @@ 994 @@ -4403,17 +4575,18 @@ static void interiorReaderInit(const char *pData, int nD ata,
1082 if( pReader->nData==0 ){ 995 if( pReader->nData==0 ){
1083 dataBufferInit(&pReader->term, 0); 996 dataBufferInit(&pReader->term, 0);
1084 }else{ 997 }else{
1085 - n = getVarint32(pReader->pData, &nTerm); 998 - n = getVarint32(pReader->pData, &nTerm);
1086 + n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData); 999 + n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData);
1087 + if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT; 1000 + if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT;
1088 dataBufferInit(&pReader->term, nTerm); 1001 dataBufferInit(&pReader->term, nTerm);
1089 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); 1002 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
1090 - assert( n+nTerm<=pReader->nData ); 1003 - assert( n+nTerm<=pReader->nData );
1091 pReader->pData += n+nTerm; 1004 pReader->pData += n+nTerm;
1092 pReader->nData -= n+nTerm; 1005 pReader->nData -= n+nTerm;
1093 } 1006 }
1094 + return SQLITE_OK; 1007 + return SQLITE_OK;
1095 } 1008 }
1096 1009
1097 static int interiorReaderAtEnd(InteriorReader *pReader){ 1010 static int interiorReaderAtEnd(InteriorReader *pReader){
1098 - return pReader->term.nData==0; 1011 - return pReader->term.nData==0;
1099 + return pReader->term.nData<=0; 1012 + return pReader->term.nData<=0;
1100 } 1013 }
1101 1014
1102 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ 1015 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
1103 @@ -4388,7 +4603,7 @@ 1016 @@ -4430,7 +4603,7 @@ static const char *interiorReaderTerm(InteriorReader *pRea der){
1104 } 1017 }
1105 1018
1106 /* Step forward to the next term in the node. */ 1019 /* Step forward to the next term in the node. */
1107 -static void interiorReaderStep(InteriorReader *pReader){ 1020 -static void interiorReaderStep(InteriorReader *pReader){
1108 +static int interiorReaderStep(InteriorReader *pReader){ 1021 +static int interiorReaderStep(InteriorReader *pReader){
1109 assert( !interiorReaderAtEnd(pReader) ); 1022 assert( !interiorReaderAtEnd(pReader) );
1110 1023
1111 /* If the last term has been read, signal eof, else construct the 1024 /* If the last term has been read, signal eof, else construct the
1112 @@ -4399,18 +4614,26 @@ 1025 @@ -4441,18 +4614,26 @@ static void interiorReaderStep(InteriorReader *pReader){
1113 }else{ 1026 }else{
1114 int n, nPrefix, nSuffix; 1027 int n, nPrefix, nSuffix;
1115 1028
1116 - n = getVarint32(pReader->pData, &nPrefix); 1029 - n = getVarint32(pReader->pData, &nPrefix);
1117 - n += getVarint32(pReader->pData+n, &nSuffix); 1030 - n += getVarint32(pReader->pData+n, &nSuffix);
1118 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData); 1031 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1119 + if( !n ) return SQLITE_CORRUPT_BKPT; 1032 + if( !n ) return SQLITE_CORRUPT_BKPT;
1120 + pReader->nData -= n; 1033 + pReader->nData -= n;
1121 + pReader->pData += n; 1034 + pReader->pData += n;
1122 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData); 1035 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
(...skipping 12 matching lines...) Expand all
1135 - pReader->pData += n+nSuffix; 1048 - pReader->pData += n+nSuffix;
1136 - pReader->nData -= n+nSuffix; 1049 - pReader->nData -= n+nSuffix;
1137 + pReader->pData += nSuffix; 1050 + pReader->pData += nSuffix;
1138 + pReader->nData -= nSuffix; 1051 + pReader->nData -= nSuffix;
1139 } 1052 }
1140 pReader->iBlockid++; 1053 pReader->iBlockid++;
1141 + return SQLITE_OK; 1054 + return SQLITE_OK;
1142 } 1055 }
1143 1056
1144 /* Compare the current term to pTerm[nTerm], returning strcmp-style 1057 /* Compare the current term to pTerm[nTerm], returning strcmp-style
1145 @@ -4782,7 +5005,8 @@ 1058 @@ -4824,7 +5005,8 @@ static int leafWriterStepMerge(fulltext_vtab *v, LeafWrite r *pWriter,
1146 n = putVarint(c, nData); 1059 n = putVarint(c, nData);
1147 dataBufferAppend(&pWriter->data, c, n); 1060 dataBufferAppend(&pWriter->data, c, n);
1148 1061
1149 - docListMerge(&pWriter->data, pReaders, nReaders); 1062 - docListMerge(&pWriter->data, pReaders, nReaders);
1150 + rc = docListMerge(&pWriter->data, pReaders, nReaders); 1063 + rc = docListMerge(&pWriter->data, pReaders, nReaders);
1151 + if( rc!= SQLITE_OK ) return rc; 1064 + if( rc!= SQLITE_OK ) return rc;
1152 ASSERT_VALID_DOCLIST(DL_DEFAULT, 1065 ASSERT_VALID_DOCLIST(DL_DEFAULT,
1153 pWriter->data.pData+iDoclistData+n, 1066 pWriter->data.pData+iDoclistData+n,
1154 pWriter->data.nData-iDoclistData-n, NULL); 1067 pWriter->data.nData-iDoclistData-n, NULL);
1155 @@ -4892,7 +5116,8 @@ 1068 @@ -4934,7 +5116,8 @@ static int leafWriterStep(fulltext_vtab *v, LeafWriter *pW riter,
1156 int rc; 1069 int rc;
1157 DLReader reader; 1070 DLReader reader;
1158 1071
1159 - dlrInit(&reader, DL_DEFAULT, pData, nData); 1072 - dlrInit(&reader, DL_DEFAULT, pData, nData);
1160 + rc = dlrInit(&reader, DL_DEFAULT, pData, nData); 1073 + rc = dlrInit(&reader, DL_DEFAULT, pData, nData);
1161 + if( rc!=SQLITE_OK ) return rc; 1074 + if( rc!=SQLITE_OK ) return rc;
1162 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); 1075 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
1163 dlrDestroy(&reader); 1076 dlrDestroy(&reader);
1164 1077
1165 @@ -4937,38 +5162,40 @@ 1078 @@ -4979,38 +5162,40 @@ static int leafReaderDataBytes(LeafReader *pReader){
1166 static const char *leafReaderData(LeafReader *pReader){ 1079 static const char *leafReaderData(LeafReader *pReader){
1167 int n, nData; 1080 int n, nData;
1168 assert( pReader->term.nData>0 ); 1081 assert( pReader->term.nData>0 );
1169 - n = getVarint32(pReader->pData, &nData); 1082 - n = getVarint32(pReader->pData, &nData);
1170 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData); 1083 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1171 + if( !n || nData>pReader->nData-n ) return NULL; 1084 + if( !n || nData>pReader->nData-n ) return NULL;
1172 return pReader->pData+n; 1085 return pReader->pData+n;
1173 } 1086 }
1174 1087
1175 -static void leafReaderInit(const char *pData, int nData, 1088 -static void leafReaderInit(const char *pData, int nData,
(...skipping 28 matching lines...) Expand all
1204 assert( !leafReaderAtEnd(pReader) ); 1117 assert( !leafReaderAtEnd(pReader) );
1205 1118
1206 /* Skip previous entry's data block. */ 1119 /* Skip previous entry's data block. */
1207 - n = getVarint32(pReader->pData, &nData); 1120 - n = getVarint32(pReader->pData, &nData);
1208 - assert( n+nData<=pReader->nData ); 1121 - assert( n+nData<=pReader->nData );
1209 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData); 1122 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1210 + if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT; 1123 + if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT;
1211 pReader->pData += n+nData; 1124 pReader->pData += n+nData;
1212 pReader->nData -= n+nData; 1125 pReader->nData -= n+nData;
1213 1126
1214 @@ -4976,15 +5203,23 @@ 1127 @@ -5018,15 +5203,23 @@ static void leafReaderStep(LeafReader *pReader){
1215 /* Construct the new term using a prefix from the old term plus a 1128 /* Construct the new term using a prefix from the old term plus a
1216 ** suffix from the leaf data. 1129 ** suffix from the leaf data.
1217 */ 1130 */
1218 - n = getVarint32(pReader->pData, &nPrefix); 1131 - n = getVarint32(pReader->pData, &nPrefix);
1219 - n += getVarint32(pReader->pData+n, &nSuffix); 1132 - n += getVarint32(pReader->pData+n, &nSuffix);
1220 - assert( n+nSuffix<pReader->nData ); 1133 - assert( n+nSuffix<pReader->nData );
1221 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData); 1134 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1222 + if( !n ) return SQLITE_CORRUPT_BKPT; 1135 + if( !n ) return SQLITE_CORRUPT_BKPT;
1223 + pReader->nData -= n; 1136 + pReader->nData -= n;
1224 + pReader->pData += n; 1137 + pReader->pData += n;
1225 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData); 1138 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
1226 + if( !n ) return SQLITE_CORRUPT_BKPT; 1139 + if( !n ) return SQLITE_CORRUPT_BKPT;
1227 + pReader->nData -= n; 1140 + pReader->nData -= n;
1228 + pReader->pData += n; 1141 + pReader->pData += n;
1229 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT; 1142 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
1230 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT; 1143 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
1231 pReader->term.nData = nPrefix; 1144 pReader->term.nData = nPrefix;
1232 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); 1145 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
1233 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix); 1146 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
1234 1147
1235 - pReader->pData += n+nSuffix; 1148 - pReader->pData += n+nSuffix;
1236 - pReader->nData -= n+nSuffix; 1149 - pReader->nData -= n+nSuffix;
1237 + pReader->pData += nSuffix; 1150 + pReader->pData += nSuffix;
1238 + pReader->nData -= nSuffix; 1151 + pReader->nData -= nSuffix;
1239 } 1152 }
1240 + return SQLITE_OK; 1153 + return SQLITE_OK;
1241 } 1154 }
1242 1155
1243 /* strcmp-style comparison of pReader's current term against pTerm. 1156 /* strcmp-style comparison of pReader's current term against pTerm.
1244 @@ -5077,6 +5312,9 @@ 1157 @@ -5133,14 +5326,19 @@ static int leavesReaderInit(fulltext_vtab *v,
1245 ** the leaf data was entirely contained in the root), or from the
1246 ** stream of blocks between iStartBlockid and iEndBlockid, inclusive.
1247 */
1248 +/* TODO(shess): Figure out a means of indicating how many leaves are
1249 +** expected, for purposes of detecting corruption.
1250 +*/
1251 static int leavesReaderInit(fulltext_vtab *v,
1252 int idx,
1253 sqlite_int64 iStartBlockid,
1254 @@ -5088,32 +5326,67 @@
1255 1158
1256 dataBufferInit(&pReader->rootData, 0); 1159 dataBufferInit(&pReader->rootData, 0);
1257 if( iStartBlockid==0 ){ 1160 if( iStartBlockid==0 ){
1258 + int rc; 1161 + int rc;
1259 + /* Corrupt if this can't be a leaf node. */ 1162 /* Corrupt if this can't be a leaf node. */
1260 + if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){ 1163 if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){
1261 + return SQLITE_CORRUPT_BKPT; 1164 return SQLITE_CORRUPT_BKPT;
1262 + } 1165 }
1263 /* Entire leaf level fit in root data. */ 1166 /* Entire leaf level fit in root data. */
1264 dataBufferReplace(&pReader->rootData, pRootData, nRootData); 1167 dataBufferReplace(&pReader->rootData, pRootData, nRootData);
1265 - leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, 1168 - leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
1266 - &pReader->leafReader); 1169 - &pReader->leafReader);
1267 + rc = leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, 1170 + rc = leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
1268 + &pReader->leafReader); 1171 + &pReader->leafReader);
1269 + if( rc!=SQLITE_OK ){ 1172 + if( rc!=SQLITE_OK ){
1270 + dataBufferDestroy(&pReader->rootData); 1173 + dataBufferDestroy(&pReader->rootData);
1271 + return rc; 1174 + return rc;
1272 + } 1175 + }
1273 }else{ 1176 }else{
1274 sqlite3_stmt *s; 1177 sqlite3_stmt *s;
1275 int rc = sql_get_leaf_statement(v, idx, &s); 1178 int rc = sql_get_leaf_statement(v, idx, &s);
1276 if( rc!=SQLITE_OK ) return rc; 1179 @@ -5174,7 +5372,7 @@ static int leavesReaderInit(fulltext_vtab *v,
1180 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
1181 rc = SQLITE_CORRUPT_BKPT;
1182 }else{
1183 - leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1184 + rc = leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1185 }
1186 }
1277 1187
1278 rc = sqlite3_bind_int64(s, 1, iStartBlockid); 1188 @@ -5197,11 +5395,12 @@ static int leavesReaderInit(fulltext_vtab *v,
1279 - if( rc!=SQLITE_OK ) return rc;
1280 + if( rc!=SQLITE_OK ) goto err;
1281
1282 rc = sqlite3_bind_int64(s, 2, iEndBlockid);
1283 - if( rc!=SQLITE_OK ) return rc;
1284 + if( rc!=SQLITE_OK ) goto err;
1285
1286 rc = sqlite3_step(s);
1287 +
1288 + /* Corrupt if interior node referenced missing leaf node. */
1289 if( rc==SQLITE_DONE ){
1290 - pReader->eof = 1;
1291 - return SQLITE_OK;
1292 + rc = SQLITE_CORRUPT_BKPT;
1293 + goto err;
1294 + }
1295 +
1296 + if( rc!=SQLITE_ROW ) goto err;
1297 + rc = SQLITE_OK;
1298 +
1299 + /* Corrupt if leaf data isn't a blob. */
1300 + if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){
1301 + rc = SQLITE_CORRUPT_BKPT;
1302 + }else{
1303 + const char *pLeafData = sqlite3_column_blob(s, 0);
1304 + int nLeafData = sqlite3_column_bytes(s, 0);
1305 +
1306 + /* Corrupt if this can't be a leaf node. */
1307 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
1308 + rc = SQLITE_CORRUPT_BKPT;
1309 + }else{
1310 + rc = leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1311 + }
1312 + }
1313 +
1314 + err:
1315 + if( rc!=SQLITE_OK ){
1316 + if( idx==-1 ){
1317 + sqlite3_finalize(s);
1318 + }else{
1319 + sqlite3_reset(s);
1320 + }
1321 + return rc;
1322 }
1323 - if( rc!=SQLITE_ROW ) return rc;
1324
1325 pReader->pStmt = s;
1326 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
1327 - sqlite3_column_bytes(pReader->pStmt, 0),
1328 - &pReader->leafReader);
1329 }
1330 return SQLITE_OK;
1331 }
1332 @@ -5122,11 +5395,12 @@
1333 ** end of the current leaf, step forward to the next leaf block. 1189 ** end of the current leaf, step forward to the next leaf block.
1334 */ 1190 */
1335 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ 1191 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1336 + int rc; 1192 + int rc;
1337 assert( !leavesReaderAtEnd(pReader) ); 1193 assert( !leavesReaderAtEnd(pReader) );
1338 - leafReaderStep(&pReader->leafReader); 1194 - leafReaderStep(&pReader->leafReader);
1339 + rc = leafReaderStep(&pReader->leafReader); 1195 + rc = leafReaderStep(&pReader->leafReader);
1340 + if( rc!=SQLITE_OK ) return rc; 1196 + if( rc!=SQLITE_OK ) return rc;
1341 1197
1342 if( leafReaderAtEnd(&pReader->leafReader) ){ 1198 if( leafReaderAtEnd(&pReader->leafReader) ){
1343 - int rc; 1199 - int rc;
1344 if( pReader->rootData.pData ){ 1200 if( pReader->rootData.pData ){
1345 pReader->eof = 1; 1201 pReader->eof = 1;
1346 return SQLITE_OK; 1202 return SQLITE_OK;
1347 @@ -5136,10 +5410,25 @@ 1203 @@ -5216,6 +5415,7 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1348 pReader->eof = 1; 1204 if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
1349 return rc==SQLITE_DONE ? SQLITE_OK : rc; 1205 return SQLITE_CORRUPT_BKPT;
1350 } 1206 }else{
1351 - leafReaderDestroy(&pReader->leafReader);
1352 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
1353 - sqlite3_column_bytes(pReader->pStmt, 0),
1354 - &pReader->leafReader);
1355 +
1356 + /* Corrupt if leaf data isn't a blob. */
1357 + if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
1358 + return SQLITE_CORRUPT_BKPT;
1359 + }else{
1360 + LeafReader tmp; 1207 + LeafReader tmp;
1361 + const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0); 1208 const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0);
1362 + int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0); 1209 int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0);
1363 + 1210
1364 + /* Corrupt if this can't be a leaf node. */ 1211 @@ -5224,8 +5424,10 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesReade r *pReader){
1365 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){ 1212 return SQLITE_CORRUPT_BKPT;
1366 + return SQLITE_CORRUPT_BKPT; 1213 }
1367 + } 1214
1368 +
1369 + rc = leafReaderInit(pLeafData, nLeafData, &tmp); 1215 + rc = leafReaderInit(pLeafData, nLeafData, &tmp);
1370 + if( rc!=SQLITE_OK ) return rc; 1216 + if( rc!=SQLITE_OK ) return rc;
1371 + leafReaderDestroy(&pReader->leafReader); 1217 leafReaderDestroy(&pReader->leafReader);
1218 - leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1372 + pReader->leafReader = tmp; 1219 + pReader->leafReader = tmp;
1373 + } 1220 }
1374 } 1221 }
1375 return SQLITE_OK; 1222 return SQLITE_OK;
1376 } 1223 @@ -5334,13 +5536,26 @@ static int leavesReadersMerge(fulltext_vtab *v,
1377 @@ -5200,8 +5489,19 @@
1378 sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
1379 const char *pRootData = sqlite3_column_blob(s, 2);
1380 int nRootData = sqlite3_column_bytes(s, 2);
1381 + sqlite_int64 iIndex = sqlite3_column_int64(s, 3);
1382 +
1383 + /* Corrupt if we get back different types than we stored. */
1384 + /* Also corrupt if the index is not sequential starting at 0. */
1385 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1386 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1387 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ||
1388 + i!=iIndex ||
1389 + i>=MERGE_COUNT ){
1390 + rc = SQLITE_CORRUPT_BKPT;
1391 + break;
1392 + }
1393
1394 - assert( i<MERGE_COUNT );
1395 rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData,
1396 &pReaders[i]);
1397 if( rc!=SQLITE_OK ) break;
1398 @@ -5212,6 +5512,7 @@
1399 while( i-->0 ){
1400 leavesReaderDestroy(&pReaders[i]);
1401 }
1402 + sqlite3_reset(s); /* So we don't leave a lock. */
1403 return rc;
1404 }
1405
1406 @@ -5235,13 +5536,26 @@
1407 DLReader dlReaders[MERGE_COUNT]; 1224 DLReader dlReaders[MERGE_COUNT];
1408 const char *pTerm = leavesReaderTerm(pReaders); 1225 const char *pTerm = leavesReaderTerm(pReaders);
1409 int i, nTerm = leavesReaderTermBytes(pReaders); 1226 int i, nTerm = leavesReaderTermBytes(pReaders);
1410 + int rc; 1227 + int rc;
1411 1228
1412 assert( nReaders<=MERGE_COUNT ); 1229 assert( nReaders<=MERGE_COUNT );
1413 1230
1414 for(i=0; i<nReaders; i++){ 1231 for(i=0; i<nReaders; i++){
1415 - dlrInit(&dlReaders[i], DL_DEFAULT, 1232 - dlrInit(&dlReaders[i], DL_DEFAULT,
1416 - leavesReaderData(pReaders+i), 1233 - leavesReaderData(pReaders+i),
1417 - leavesReaderDataBytes(pReaders+i)); 1234 - leavesReaderDataBytes(pReaders+i));
1418 + const char *pData = leavesReaderData(pReaders+i); 1235 + const char *pData = leavesReaderData(pReaders+i);
1419 + if( pData==NULL ){ 1236 + if( pData==NULL ){
1420 + rc = SQLITE_CORRUPT_BKPT; 1237 + rc = SQLITE_CORRUPT_BKPT;
1421 + break; 1238 + break;
1422 + } 1239 + }
1423 + rc = dlrInit(&dlReaders[i], DL_DEFAULT, 1240 + rc = dlrInit(&dlReaders[i], DL_DEFAULT,
1424 + pData, 1241 + pData,
1425 + leavesReaderDataBytes(pReaders+i)); 1242 + leavesReaderDataBytes(pReaders+i));
1426 + if( rc!=SQLITE_OK ) break; 1243 + if( rc!=SQLITE_OK ) break;
1427 + } 1244 + }
1428 + if( rc!=SQLITE_OK ){ 1245 + if( rc!=SQLITE_OK ){
1429 + while( i-->0 ){ 1246 + while( i-->0 ){
1430 + dlrDestroy(&dlReaders[i]); 1247 + dlrDestroy(&dlReaders[i]);
1431 + } 1248 + }
1432 + return rc; 1249 + return rc;
1433 } 1250 }
1434 1251
1435 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders); 1252 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
1436 @@ -5295,10 +5609,14 @@ 1253 @@ -5444,12 +5659,14 @@ static int segmentMerge(fulltext_vtab *v, int iLevel){
1437 memset(&lrs, '\0', sizeof(lrs));
1438 rc = leavesReadersInit(v, iLevel, lrs, &i);
1439 if( rc!=SQLITE_OK ) return rc;
1440 - assert( i==MERGE_COUNT );
1441
1442 leafWriterInit(iLevel+1, idx, &writer);
1443
1444 + if( i!=MERGE_COUNT ){
1445 + rc = SQLITE_CORRUPT_BKPT;
1446 + goto err;
1447 + }
1448 +
1449 /* Since leavesReaderReorder() pushes readers at eof to the end,
1450 ** when the first reader is empty, all will be empty.
1451 */
1452 @@ -5341,12 +5659,14 @@
1453 } 1254 }
1454 1255
1455 /* Accumulate the union of *acc and *pData into *acc. */ 1256 /* Accumulate the union of *acc and *pData into *acc. */
1456 -static void docListAccumulateUnion(DataBuffer *acc, 1257 -static void docListAccumulateUnion(DataBuffer *acc,
1457 - const char *pData, int nData) { 1258 - const char *pData, int nData) {
1458 +static int docListAccumulateUnion(DataBuffer *acc, 1259 +static int docListAccumulateUnion(DataBuffer *acc,
1459 + const char *pData, int nData) { 1260 + const char *pData, int nData) {
1460 DataBuffer tmp = *acc; 1261 DataBuffer tmp = *acc;
1461 + int rc; 1262 + int rc;
1462 dataBufferInit(acc, tmp.nData+nData); 1263 dataBufferInit(acc, tmp.nData+nData);
1463 - docListUnion(tmp.pData, tmp.nData, pData, nData, acc); 1264 - docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1464 + rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc); 1265 + rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1465 dataBufferDestroy(&tmp); 1266 dataBufferDestroy(&tmp);
1466 + return rc; 1267 + return rc;
1467 } 1268 }
1468 1269
1469 /* TODO(shess) It might be interesting to explore different merge 1270 /* TODO(shess) It might be interesting to explore different merge
1470 @@ -5388,8 +5708,13 @@ 1271 @@ -5491,8 +5708,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesR eader *pReader,
1471 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); 1272 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
1472 if( c>0 ) break; /* Past any possible matches. */ 1273 if( c>0 ) break; /* Past any possible matches. */
1473 if( c==0 ){ 1274 if( c==0 ){
1474 + int iBuffer, nData; 1275 + int iBuffer, nData;
1475 const char *pData = leavesReaderData(pReader); 1276 const char *pData = leavesReaderData(pReader);
1476 - int iBuffer, nData = leavesReaderDataBytes(pReader); 1277 - int iBuffer, nData = leavesReaderDataBytes(pReader);
1477 + if( pData==NULL ){ 1278 + if( pData==NULL ){
1478 + rc = SQLITE_CORRUPT_BKPT; 1279 + rc = SQLITE_CORRUPT_BKPT;
1479 + break; 1280 + break;
1480 + } 1281 + }
1481 + nData = leavesReaderDataBytes(pReader); 1282 + nData = leavesReaderDataBytes(pReader);
1482 1283
1483 /* Find the first empty buffer. */ 1284 /* Find the first empty buffer. */
1484 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){ 1285 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
1485 @@ -5435,11 +5760,13 @@ 1286 @@ -5538,11 +5760,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, Leaves Reader *pReader,
1486 ** with pData/nData. 1287 ** with pData/nData.
1487 */ 1288 */
1488 dataBufferSwap(p, pAcc); 1289 dataBufferSwap(p, pAcc);
1489 - docListAccumulateUnion(pAcc, pData, nData); 1290 - docListAccumulateUnion(pAcc, pData, nData);
1490 + rc = docListAccumulateUnion(pAcc, pData, nData); 1291 + rc = docListAccumulateUnion(pAcc, pData, nData);
1491 + if( rc!=SQLITE_OK ) goto err; 1292 + if( rc!=SQLITE_OK ) goto err;
1492 1293
1493 /* Accumulate remaining doclists into pAcc. */ 1294 /* Accumulate remaining doclists into pAcc. */
1494 for(++p; p<pAcc; ++p){ 1295 for(++p; p<pAcc; ++p){
1495 - docListAccumulateUnion(pAcc, p->pData, p->nData); 1296 - docListAccumulateUnion(pAcc, p->pData, p->nData);
1496 + rc = docListAccumulateUnion(pAcc, p->pData, p->nData); 1297 + rc = docListAccumulateUnion(pAcc, p->pData, p->nData);
1497 + if( rc!=SQLITE_OK ) goto err; 1298 + if( rc!=SQLITE_OK ) goto err;
1498 1299
1499 /* dataBufferReset() could allow a large doclist to blow up 1300 /* dataBufferReset() could allow a large doclist to blow up
1500 ** our memory requirements. 1301 ** our memory requirements.
1501 @@ -5464,13 +5791,15 @@ 1302 @@ -5567,13 +5791,15 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, Leaves Reader *pReader,
1502 if( out->nData==0 ){ 1303 if( out->nData==0 ){
1503 dataBufferSwap(out, &(pBuffers[iBuffer])); 1304 dataBufferSwap(out, &(pBuffers[iBuffer]));
1504 }else{ 1305 }else{
1505 - docListAccumulateUnion(out, pBuffers[iBuffer].pData, 1306 - docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1506 - pBuffers[iBuffer].nData); 1307 - pBuffers[iBuffer].nData);
1507 + rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData, 1308 + rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1508 + pBuffers[iBuffer].nData); 1309 + pBuffers[iBuffer].nData);
1509 + if( rc!=SQLITE_OK ) break; 1310 + if( rc!=SQLITE_OK ) break;
1510 } 1311 }
1511 } 1312 }
1512 } 1313 }
1513 } 1314 }
1514 1315
1515 +err: 1316 +err:
1516 while( nBuffers-- ){ 1317 while( nBuffers-- ){
1517 dataBufferDestroy(&(pBuffers[nBuffers])); 1318 dataBufferDestroy(&(pBuffers[nBuffers]));
1518 } 1319 }
1519 @@ -5529,20 +5858,26 @@ 1320 @@ -5632,20 +5858,26 @@ static int loadSegmentLeaves(fulltext_vtab *v,
1520 ** node. Consider whether breaking symmetry is worthwhile. I suspect 1321 ** node. Consider whether breaking symmetry is worthwhile. I suspect
1521 ** it is not worthwhile. 1322 ** it is not worthwhile.
1522 */ 1323 */
1523 -static void getChildrenContaining(const char *pData, int nData, 1324 -static void getChildrenContaining(const char *pData, int nData,
1524 - const char *pTerm, int nTerm, int isPrefix, 1325 - const char *pTerm, int nTerm, int isPrefix,
1525 - sqlite_int64 *piStartChild, 1326 - sqlite_int64 *piStartChild,
1526 - sqlite_int64 *piEndChild){ 1327 - sqlite_int64 *piEndChild){
1527 +static int getChildrenContaining(const char *pData, int nData, 1328 +static int getChildrenContaining(const char *pData, int nData,
1528 + const char *pTerm, int nTerm, int isPrefix, 1329 + const char *pTerm, int nTerm, int isPrefix,
1529 + sqlite_int64 *piStartChild, 1330 + sqlite_int64 *piStartChild,
(...skipping 12 matching lines...) Expand all
1542 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; 1343 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
1543 - interiorReaderStep(&reader); 1344 - interiorReaderStep(&reader);
1544 + rc = interiorReaderStep(&reader); 1345 + rc = interiorReaderStep(&reader);
1545 + if( rc!=SQLITE_OK ){ 1346 + if( rc!=SQLITE_OK ){
1546 + interiorReaderDestroy(&reader); 1347 + interiorReaderDestroy(&reader);
1547 + return rc; 1348 + return rc;
1548 + } 1349 + }
1549 } 1350 }
1550 *piStartChild = interiorReaderCurrentBlockid(&reader); 1351 *piStartChild = interiorReaderCurrentBlockid(&reader);
1551 1352
1552 @@ -5552,7 +5887,11 @@ 1353 @@ -5655,7 +5887,11 @@ static void getChildrenContaining(const char *pData, int nData,
1553 */ 1354 */
1554 while( !interiorReaderAtEnd(&reader) ){ 1355 while( !interiorReaderAtEnd(&reader) ){
1555 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; 1356 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
1556 - interiorReaderStep(&reader); 1357 - interiorReaderStep(&reader);
1557 + rc = interiorReaderStep(&reader); 1358 + rc = interiorReaderStep(&reader);
1558 + if( rc!=SQLITE_OK ){ 1359 + if( rc!=SQLITE_OK ){
1559 + interiorReaderDestroy(&reader); 1360 + interiorReaderDestroy(&reader);
1560 + return rc; 1361 + return rc;
1561 + } 1362 + }
1562 } 1363 }
1563 *piEndChild = interiorReaderCurrentBlockid(&reader); 1364 *piEndChild = interiorReaderCurrentBlockid(&reader);
1564 1365
1565 @@ -5561,6 +5900,7 @@ 1366 @@ -5664,6 +5900,7 @@ static void getChildrenContaining(const char *pData, int n Data,
1566 /* Children must ascend, and if !prefix, both must be the same. */ 1367 /* Children must ascend, and if !prefix, both must be the same. */
1567 assert( *piEndChild>=*piStartChild ); 1368 assert( *piEndChild>=*piStartChild );
1568 assert( isPrefix || *piStartChild==*piEndChild ); 1369 assert( isPrefix || *piStartChild==*piEndChild );
1569 + return rc; 1370 + return rc;
1570 } 1371 }
1571 1372
1572 /* Read block at iBlockid and pass it with other params to 1373 /* Read block at iBlockid and pass it with other params to
1573 @@ -5588,11 +5928,31 @@ 1374 @@ -5709,8 +5946,12 @@ static int loadAndGetChildrenContaining(
1574 if( rc!=SQLITE_OK ) return rc; 1375 return SQLITE_CORRUPT_BKPT;
1376 }
1575 1377
1576 rc = sqlite3_step(s); 1378 - getChildrenContaining(pData, nData, pTerm, nTerm,
1577 - if( rc==SQLITE_DONE ) return SQLITE_ERROR; 1379 - isPrefix, piStartChild, piEndChild);
1578 + /* Corrupt if interior node references missing child node. */
1579 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
1580 if( rc!=SQLITE_ROW ) return rc;
1581
1582 - getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
1583 - pTerm, nTerm, isPrefix, piStartChild, piEndChild);
1584 + /* Corrupt if child node isn't a blob. */
1585 + if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){
1586 + sqlite3_reset(s); /* So we don't leave a lock. */
1587 + return SQLITE_CORRUPT_BKPT;
1588 + }else{
1589 + const char *pData = sqlite3_column_blob(s, 0);
1590 + int nData = sqlite3_column_bytes(s, 0);
1591 +
1592 + /* Corrupt if child is not a valid interior node. */
1593 + if( pData==NULL || nData<1 || pData[0]=='\0' ){
1594 + sqlite3_reset(s); /* So we don't leave a lock. */
1595 + return SQLITE_CORRUPT_BKPT;
1596 + }
1597 +
1598 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, 1380 + rc = getChildrenContaining(pData, nData, pTerm, nTerm,
1599 + isPrefix, piStartChild, piEndChild); 1381 + isPrefix, piStartChild, piEndChild);
1600 + if( rc!=SQLITE_OK ){ 1382 + if( rc!=SQLITE_OK ){
1601 + sqlite3_reset(s); 1383 + sqlite3_reset(s);
1602 + return rc; 1384 + return rc;
1603 + } 1385 + }
1604 + } 1386 }
1605 1387
1606 /* We expect only one row. We must execute another sqlite3_step() 1388 /* We expect only one row. We must execute another sqlite3_step()
1607 * to complete the iteration; otherwise the table will remain 1389 @@ -5741,8 +5982,9 @@ static int loadSegmentInt(fulltext_vtab *v, const char *pD ata, int nData,
1608 @@ -5622,8 +5982,9 @@
1609 /* Process pData as an interior node, then loop down the tree 1390 /* Process pData as an interior node, then loop down the tree
1610 ** until we find the set of leaf nodes to scan for the term. 1391 ** until we find the set of leaf nodes to scan for the term.
1611 */ 1392 */
1612 - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, 1393 - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1613 - &iStartChild, &iEndChild); 1394 - &iStartChild, &iEndChild);
1614 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, 1395 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1615 + &iStartChild, &iEndChild); 1396 + &iStartChild, &iEndChild);
1616 + if( rc!=SQLITE_OK ) return rc; 1397 + if( rc!=SQLITE_OK ) return rc;
1617 while( iStartChild>iLeavesEnd ){ 1398 while( iStartChild>iLeavesEnd ){
1618 sqlite_int64 iNextStart, iNextEnd; 1399 sqlite_int64 iNextStart, iNextEnd;
1619 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, 1400 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
1620 @@ -5675,7 +6036,8 @@ 1401 @@ -5812,16 +6054,21 @@ static int loadSegment(fulltext_vtab *v, const char *pDa ta, int nData,
1621 DataBuffer result;
1622 int rc;
1623
1624 - assert( nData>1 );
1625 + /* Corrupt if segment root can't be valid. */
1626 + if( pData==NULL || nData<1 ) return SQLITE_CORRUPT_BKPT;
1627
1628 /* This code should never be called with buffered updates. */
1629 assert( v->nPendingData<0 );
1630 @@ -5692,16 +6054,21 @@
1631 DataBuffer merged; 1402 DataBuffer merged;
1632 DLReader readers[2]; 1403 DLReader readers[2];
1633 1404
1634 - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); 1405 - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1635 - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); 1406 - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1636 - dataBufferInit(&merged, out->nData+result.nData); 1407 - dataBufferInit(&merged, out->nData+result.nData);
1637 - docListMerge(&merged, readers, 2); 1408 - docListMerge(&merged, readers, 2);
1638 - dataBufferDestroy(out); 1409 - dataBufferDestroy(out);
1639 - *out = merged; 1410 - *out = merged;
1640 - dlrDestroy(&readers[0]); 1411 - dlrDestroy(&readers[0]);
1641 - dlrDestroy(&readers[1]); 1412 - dlrDestroy(&readers[1]);
1642 + rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); 1413 + rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1643 + if( rc==SQLITE_OK ){ 1414 + if( rc==SQLITE_OK ){
1644 + rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); 1415 + rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1645 + if( rc==SQLITE_OK ){ 1416 + if( rc==SQLITE_OK ){
1646 + dataBufferInit(&merged, out->nData+result.nData); 1417 + dataBufferInit(&merged, out->nData+result.nData);
1647 + rc = docListMerge(&merged, readers, 2); 1418 + rc = docListMerge(&merged, readers, 2);
1648 + dataBufferDestroy(out); 1419 + dataBufferDestroy(out);
1649 + *out = merged; 1420 + *out = merged;
1650 + dlrDestroy(&readers[1]); 1421 + dlrDestroy(&readers[1]);
1651 + } 1422 + }
1652 + dlrDestroy(&readers[0]); 1423 + dlrDestroy(&readers[0]);
1653 + } 1424 + }
1654 } 1425 }
1655 } 1426 }
1656 + 1427 +
1657 dataBufferDestroy(&result); 1428 dataBufferDestroy(&result);
1658 return rc; 1429 return rc;
1659 } 1430 }
1660 @@ -5729,11 +6096,20 @@ 1431 @@ -5862,6 +6109,7 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1661 const char *pData = sqlite3_column_blob(s, 2);
1662 const int nData = sqlite3_column_bytes(s, 2);
1663 const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
1664 +
1665 + /* Corrupt if we get back different types than we stored. */
1666 + if( sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1667 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1668 + rc = SQLITE_CORRUPT_BKPT;
1669 + goto err;
1670 + }
1671 +
1672 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
1673 &doclist);
1674 if( rc!=SQLITE_OK ) goto err; 1432 if( rc!=SQLITE_OK ) goto err;
1675 } 1433 }
1676 if( rc==SQLITE_DONE ){ 1434 if( rc==SQLITE_DONE ){
1677 + rc = SQLITE_OK; 1435 + rc = SQLITE_OK;
1678 if( doclist.nData!=0 ){ 1436 if( doclist.nData!=0 ){
1679 /* TODO(shess) The old term_select_all() code applied the column 1437 /* TODO(shess) The old term_select_all() code applied the column
1680 ** restrict as we merged segments, leading to smaller buffers. 1438 ** restrict as we merged segments, leading to smaller buffers.
1681 @@ -5741,13 +6117,13 @@ 1439 @@ -5869,10 +6117,9 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1682 ** system is checked in. 1440 ** system is checked in.
1683 */ 1441 */
1684 if( iColumn==v->nColumn) iColumn = -1; 1442 if( iColumn==v->nColumn) iColumn = -1;
1685 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1443 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1686 - iColumn, iType, out); 1444 - iColumn, iType, out);
1687 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1445 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1688 + iColumn, iType, out); 1446 + iColumn, iType, out);
1689 } 1447 }
1690 - rc = SQLITE_OK; 1448 - rc = SQLITE_OK;
1691 } 1449 }
1692 1450
1693 err: 1451 err:
1694 + sqlite3_reset(s); /* So we don't leave a lock. */ 1452 @@ -6218,6 +6465,7 @@ static int optimizeInternal(fulltext_vtab *v,
1695 dataBufferDestroy(&doclist);
1696 return rc;
1697 }
1698 @@ -6089,6 +6465,7 @@
1699 LeafWriter *pWriter){ 1453 LeafWriter *pWriter){
1700 int i, rc = SQLITE_OK; 1454 int i, rc = SQLITE_OK;
1701 DataBuffer doclist, merged, tmp; 1455 DataBuffer doclist, merged, tmp;
1702 + const char *pData; 1456 + const char *pData;
1703 1457
1704 /* Order the readers. */ 1458 /* Order the readers. */
1705 i = nReaders; 1459 i = nReaders;
1706 @@ -6109,14 +6486,21 @@ 1460 @@ -6238,14 +6486,21 @@ static int optimizeInternal(fulltext_vtab *v,
1707 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break; 1461 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
1708 } 1462 }
1709 1463
1710 + pData = optLeavesReaderData(&readers[0]); 1464 + pData = optLeavesReaderData(&readers[0]);
1711 + if( pData==NULL ){ 1465 + if( pData==NULL ){
1712 + rc = SQLITE_CORRUPT_BKPT; 1466 + rc = SQLITE_CORRUPT_BKPT;
1713 + break; 1467 + break;
1714 + } 1468 + }
1715 + 1469 +
1716 /* Special-case for no merge. */ 1470 /* Special-case for no merge. */
1717 if( i==1 ){ 1471 if( i==1 ){
1718 /* Trim deletions from the doclist. */ 1472 /* Trim deletions from the doclist. */
1719 dataBufferReset(&merged); 1473 dataBufferReset(&merged);
1720 - docListTrim(DL_DEFAULT, 1474 - docListTrim(DL_DEFAULT,
1721 - optLeavesReaderData(&readers[0]), 1475 - optLeavesReaderData(&readers[0]),
1722 - optLeavesReaderDataBytes(&readers[0]), 1476 - optLeavesReaderDataBytes(&readers[0]),
1723 - -1, DL_DEFAULT, &merged); 1477 - -1, DL_DEFAULT, &merged);
1724 + rc = docListTrim(DL_DEFAULT, 1478 + rc = docListTrim(DL_DEFAULT,
1725 + pData, 1479 + pData,
1726 + optLeavesReaderDataBytes(&readers[0]), 1480 + optLeavesReaderDataBytes(&readers[0]),
1727 + -1, DL_DEFAULT, &merged); 1481 + -1, DL_DEFAULT, &merged);
1728 + if( rc!= SQLITE_OK ) break; 1482 + if( rc!= SQLITE_OK ) break;
1729 }else{ 1483 }else{
1730 DLReader dlReaders[MERGE_COUNT]; 1484 DLReader dlReaders[MERGE_COUNT];
1731 int iReader, nReaders; 1485 int iReader, nReaders;
1732 @@ -6124,9 +6508,10 @@ 1486 @@ -6253,9 +6508,10 @@ static int optimizeInternal(fulltext_vtab *v,
1733 /* Prime the pipeline with the first reader's doclist. After 1487 /* Prime the pipeline with the first reader's doclist. After
1734 ** one pass index 0 will reference the accumulated doclist. 1488 ** one pass index 0 will reference the accumulated doclist.
1735 */ 1489 */
1736 - dlrInit(&dlReaders[0], DL_DEFAULT, 1490 - dlrInit(&dlReaders[0], DL_DEFAULT,
1737 - optLeavesReaderData(&readers[0]), 1491 - optLeavesReaderData(&readers[0]),
1738 - optLeavesReaderDataBytes(&readers[0])); 1492 - optLeavesReaderDataBytes(&readers[0]));
1739 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, 1493 + rc = dlrInit(&dlReaders[0], DL_DEFAULT,
1740 + pData, 1494 + pData,
1741 + optLeavesReaderDataBytes(&readers[0])); 1495 + optLeavesReaderDataBytes(&readers[0]));
1742 + if( rc!=SQLITE_OK ) break; 1496 + if( rc!=SQLITE_OK ) break;
1743 iReader = 1; 1497 iReader = 1;
1744 1498
1745 assert( iReader<i ); /* Must execute the loop at least once. */ 1499 assert( iReader<i ); /* Must execute the loop at least once. */
1746 @@ -6134,24 +6519,35 @@ 1500 @@ -6263,24 +6519,35 @@ static int optimizeInternal(fulltext_vtab *v,
1747 /* Merge 16 inputs per pass. */ 1501 /* Merge 16 inputs per pass. */
1748 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT; 1502 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
1749 iReader++, nReaders++ ){ 1503 iReader++, nReaders++ ){
1750 - dlrInit(&dlReaders[nReaders], DL_DEFAULT, 1504 - dlrInit(&dlReaders[nReaders], DL_DEFAULT,
1751 - optLeavesReaderData(&readers[iReader]), 1505 - optLeavesReaderData(&readers[iReader]),
1752 - optLeavesReaderDataBytes(&readers[iReader])); 1506 - optLeavesReaderDataBytes(&readers[iReader]));
1753 + pData = optLeavesReaderData(&readers[iReader]); 1507 + pData = optLeavesReaderData(&readers[iReader]);
1754 + if( pData == NULL ){ 1508 + if( pData == NULL ){
1755 + rc = SQLITE_CORRUPT_BKPT; 1509 + rc = SQLITE_CORRUPT_BKPT;
1756 + break; 1510 + break;
(...skipping 24 matching lines...) Expand all
1781 1535
1782 + if( rc!=SQLITE_OK ) goto err; 1536 + if( rc!=SQLITE_OK ) goto err;
1783 + 1537 +
1784 /* Accumulated doclist to reader 0 for next pass. */ 1538 /* Accumulated doclist to reader 0 for next pass. */
1785 - dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); 1539 - dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1786 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); 1540 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1787 + if( rc!=SQLITE_OK ) goto err; 1541 + if( rc!=SQLITE_OK ) goto err;
1788 } 1542 }
1789 1543
1790 /* Destroy reader that was left in the pipeline. */ 1544 /* Destroy reader that was left in the pipeline. */
1791 @@ -6159,8 +6555,9 @@ 1545 @@ -6288,8 +6555,9 @@ static int optimizeInternal(fulltext_vtab *v,
1792 1546
1793 /* Trim deletions from the doclist. */ 1547 /* Trim deletions from the doclist. */
1794 dataBufferReset(&merged); 1548 dataBufferReset(&merged);
1795 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1549 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1796 - -1, DL_DEFAULT, &merged); 1550 - -1, DL_DEFAULT, &merged);
1797 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1551 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1798 + -1, DL_DEFAULT, &merged); 1552 + -1, DL_DEFAULT, &merged);
1799 + if( rc!=SQLITE_OK ) goto err; 1553 + if( rc!=SQLITE_OK ) goto err;
1800 } 1554 }
1801 1555
1802 /* Only pass doclists with hits (skip if all hits deleted). */ 1556 /* Only pass doclists with hits (skip if all hits deleted). */
1803 @@ -6240,6 +6637,14 @@ 1557 @@ -6628,16 +6896,19 @@ static void createDoclistResult(sqlite3_context *pContex t,
1804 const char *pRootData = sqlite3_column_blob(s, 2);
1805 int nRootData = sqlite3_column_bytes(s, 2);
1806
1807 + /* Corrupt if we get back different types than we stored. */
1808 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1809 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1810 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1811 + rc = SQLITE_CORRUPT_BKPT;
1812 + break;
1813 + }
1814 +
1815 assert( i<nReaders );
1816 rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
1817 &readers[i].reader);
1818 @@ -6253,6 +6658,8 @@
1819 if( rc==SQLITE_DONE ){
1820 assert( i==nReaders );
1821 rc = optimizeInternal(v, readers, nReaders, &writer);
1822 + }else{
1823 + sqlite3_reset(s); /* So we don't leave a lock. */
1824 }
1825
1826 while( i-- > 0 ){
1827 @@ -6316,9 +6723,18 @@
1828 const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1);
1829 const char *pRootData = sqlite3_column_blob(s, 2);
1830 const int nRootData = sqlite3_column_bytes(s, 2);
1831 + int rc;
1832 LeavesReader reader;
1833 - int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
1834 - pRootData, nRootData, &reader);
1835 +
1836 + /* Corrupt if we get back different types than we stored. */
1837 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1838 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1839 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1840 + return SQLITE_CORRUPT_BKPT;
1841 + }
1842 +
1843 + rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
1844 + pRootData, nRootData, &reader);
1845 if( rc!=SQLITE_OK ) return rc;
1846
1847 while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){
1848 @@ -6480,16 +6896,19 @@
1849 const char *pData, int nData){ 1558 const char *pData, int nData){
1850 DataBuffer dump; 1559 DataBuffer dump;
1851 DLReader dlReader; 1560 DLReader dlReader;
1852 + int rc; 1561 + int rc;
1853 1562
1854 assert( pData!=NULL && nData>0 ); 1563 assert( pData!=NULL && nData>0 );
1855 1564
1856 + rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData); 1565 + rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1857 + if( rc!=SQLITE_OK ) return rc; 1566 + if( rc!=SQLITE_OK ) return;
1858 dataBufferInit(&dump, 0); 1567 dataBufferInit(&dump, 0);
1859 - dlrInit(&dlReader, DL_DEFAULT, pData, nData); 1568 - dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1860 - for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){ 1569 - for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
1861 + for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){ 1570 + for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){
1862 char buf[256]; 1571 char buf[256];
1863 PLReader plReader; 1572 PLReader plReader;
1864 1573
1865 - plrInit(&plReader, &dlReader); 1574 - plrInit(&plReader, &dlReader);
1866 + rc = plrInit(&plReader, &dlReader); 1575 + rc = plrInit(&plReader, &dlReader);
1867 + if( rc!=SQLITE_OK ) break; 1576 + if( rc!=SQLITE_OK ) break;
1868 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){ 1577 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
1869 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader)); 1578 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
1870 dataBufferAppend(&dump, buf, strlen(buf)); 1579 dataBufferAppend(&dump, buf, strlen(buf));
1871 @@ -6500,7 +6919,8 @@ 1580 @@ -6648,7 +6919,8 @@ static void createDoclistResult(sqlite3_context *pContext,
1872 dlrDocid(&dlReader), iColumn); 1581 dlrDocid(&dlReader), iColumn);
1873 dataBufferAppend(&dump, buf, strlen(buf)); 1582 dataBufferAppend(&dump, buf, strlen(buf));
1874 1583
1875 - for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){ 1584 - for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){
1876 + for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){ 1585 + for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){
1877 + if( rc!=SQLITE_OK ) break; 1586 + if( rc!=SQLITE_OK ) break;
1878 if( plrColumn(&plReader)!=iColumn ){ 1587 if( plrColumn(&plReader)!=iColumn ){
1879 iColumn = plrColumn(&plReader); 1588 iColumn = plrColumn(&plReader);
1880 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn); 1589 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
1881 @@ -6521,6 +6941,7 @@ 1590 @@ -6669,6 +6941,7 @@ static void createDoclistResult(sqlite3_context *pContext,
1882 dataBufferAppend(&dump, buf, strlen(buf)); 1591 dataBufferAppend(&dump, buf, strlen(buf));
1883 } 1592 }
1884 plrDestroy(&plReader); 1593 plrDestroy(&plReader);
1885 + if( rc!= SQLITE_OK ) break; 1594 + if( rc!= SQLITE_OK ) break;
1886 1595
1887 assert( dump.nData>0 ); 1596 assert( dump.nData>0 );
1888 dump.nData--; /* Overwrite trailing space. */ 1597 dump.nData--; /* Overwrite trailing space. */
1889 @@ -6529,6 +6950,10 @@ 1598 @@ -6677,6 +6950,10 @@ static void createDoclistResult(sqlite3_context *pContext ,
1890 } 1599 }
1891 } 1600 }
1892 dlrDestroy(&dlReader); 1601 dlrDestroy(&dlReader);
1893 + if( rc!=SQLITE_OK ){ 1602 + if( rc!=SQLITE_OK ){
1894 + dataBufferDestroy(&dump); 1603 + dataBufferDestroy(&dump);
1895 + return rc; 1604 + return;
1896 + } 1605 + }
1897 1606
1898 assert( dump.nData>0 ); 1607 assert( dump.nData>0 );
1899 dump.nData--; /* Overwrite trailing space. */ 1608 dump.nData--; /* Overwrite trailing space. */
1900 @@ -6540,6 +6965,7 @@ 1609 --
1901 sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free); 1610 2.2.1
1902 dump.pData = NULL; 1611
1903 dump.nData = dump.nCapacity = 0;
1904 + return SQLITE_OK;
1905 }
1906
1907 /* Implements dump_doclist() for use in inspecting the fts2 index from
1908 @@ -6822,7 +7248,11 @@
1909 ** module with sqlite.
1910 */
1911 if( SQLITE_OK==rc
1912 +#if GEARS_FTS2_CHANGES && !SQLITE_TEST
1913 + /* fts2_tokenizer() disabled for security reasons. */
1914 +#else
1915 && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer"))
1916 +#endif
1917 && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
1918 && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1))
1919 && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1))
1920 diff -ru ext-orig/fts2/fts2_icu.c ext/fts2/fts2_icu.c
1921 --- ext-orig/fts2/fts2_icu.c» 2009-09-03 13:32:06.000000000 -0700
1922 +++ ext/fts2/fts2_icu.c»2009-09-18 14:39:41.000000000 -0700
1923 @@ -198,7 +198,7 @@
1924
1925 while( iStart<iEnd ){
1926 int iWhite = iStart;
1927 - U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
1928 + U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
1929 if( u_isspace(c) ){
1930 iStart = iWhite;
1931 }else{
1932 diff -ru ext-orig/fts2/fts2_tokenizer.c ext/fts2/fts2_tokenizer.c
1933 --- ext-orig/fts2/fts2_tokenizer.c» 2009-09-03 13:32:06.000000000 -0700
1934 +++ ext/fts2/fts2_tokenizer.c» 2009-09-18 14:39:41.000000000 -0700
1935 @@ -28,11 +28,14 @@
1936
1937 #include "sqlite3.h"
1938 #include "sqlite3ext.h"
1939 -SQLITE_EXTENSION_INIT1
1940 +#ifndef SQLITE_CORE
1941 + SQLITE_EXTENSION_INIT1
1942 +#endif
1943
1944 #include "fts2_hash.h"
1945 #include "fts2_tokenizer.h"
1946 #include <assert.h>
1947 +#include <stddef.h>
1948
1949 /*
1950 ** Implementation of the SQL scalar function for accessing the underlying
OLDNEW
« no previous file with comments | « third_party/sqlite/patches/0022-fts2-Fix-a-crasher-in-full-text-search-sqlite.patch ('k') | third_party/sqlite/recover.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698