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

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

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

Powered by Google App Engine
This is Rietveld 408576698