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

Side by Side Diff: third_party/sqlite/fts2.patch

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

Powered by Google App Engine
This is Rietveld 408576698