Android Chromoting: Remove exit-fullscreen button.
[chromium-blink-merge.git] / third_party / sqlite / patches / 0016-fts2-Fix-numerous-out-of-bounds-bugs-reading-corrupt.patch
bloba51d1dfe77442ceeacaf189bb3c69420a0773a19
1 From 5938a2cdd5c19c9afe646425abe86d5cb75b6d1a Mon Sep 17 00:00:00 2001
2 From: Chris Evans <cevans@chromium.org>
3 Date: Wed, 30 Sep 2009 23:10:34 +0000
4 Subject: [PATCH 16/16] [fts2] Fix numerous out-of-bounds bugs reading corrupt
5 database.
7 Fix numerous bugs in fts2 where a corrupt fts2 database could cause
8 out-of-bounds reads and writes.
10 Original review URL is more descriptive:
11 http://codereview.chromium.org/216026
12 ---
13 third_party/sqlite/src/ext/fts2/fts2.c | 751 ++++++++++++++++++++++-----------
14 1 file changed, 514 insertions(+), 237 deletions(-)
16 diff --git a/third_party/sqlite/src/ext/fts2/fts2.c b/third_party/sqlite/src/ext/fts2/fts2.c
17 index a78e3d3..e585a8b 100644
18 --- a/third_party/sqlite/src/ext/fts2/fts2.c
19 +++ b/third_party/sqlite/src/ext/fts2/fts2.c
20 @@ -447,30 +447,41 @@ static int putVarint(char *p, sqlite_int64 v){
21 /* Read a 64-bit variable-length integer from memory starting at p[0].
22 * Return the number of bytes read, or 0 on error.
23 * The value is stored in *v. */
24 -static int getVarint(const char *p, sqlite_int64 *v){
25 +static int getVarintSafe(const char *p, sqlite_int64 *v, int max){
26 const unsigned char *q = (const unsigned char *) p;
27 sqlite_uint64 x = 0, y = 1;
28 - while( (*q & 0x80) == 0x80 ){
29 + if( max>VARINT_MAX ) max = VARINT_MAX;
30 + while( max && (*q & 0x80) == 0x80 ){
31 + max--;
32 x += y * (*q++ & 0x7f);
33 y <<= 7;
34 - if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */
35 - assert( 0 );
36 - return 0;
37 - }
38 + }
39 + if ( !max ){
40 + assert( 0 );
41 + return 0; /* tried to read too much; bad data */
43 x += y * (*q++);
44 *v = (sqlite_int64) x;
45 return (int) (q - (unsigned char *)p);
48 -static int getVarint32(const char *p, int *pi){
49 +static int getVarint(const char *p, sqlite_int64 *v){
50 + return getVarintSafe(p, v, VARINT_MAX);
53 +static int getVarint32Safe(const char *p, int *pi, int max){
54 sqlite_int64 i;
55 - int ret = getVarint(p, &i);
56 + int ret = getVarintSafe(p, &i, max);
57 + if( !ret ) return ret;
58 *pi = (int) i;
59 assert( *pi==i );
60 return ret;
63 +static int getVarint32(const char* p, int *pi){
64 + return getVarint32Safe(p, pi, VARINT_MAX);
67 /*******************************************************************/
68 /* DataBuffer is used to collect data into a buffer in piecemeal
69 ** fashion. It implements the usual distinction between amount of
70 @@ -639,7 +650,7 @@ typedef struct DLReader {
72 static int dlrAtEnd(DLReader *pReader){
73 assert( pReader->nData>=0 );
74 - return pReader->nData==0;
75 + return pReader->nData<=0;
77 static sqlite_int64 dlrDocid(DLReader *pReader){
78 assert( !dlrAtEnd(pReader) );
79 @@ -663,7 +674,8 @@ static int dlrAllDataBytes(DLReader *pReader){
81 static const char *dlrPosData(DLReader *pReader){
82 sqlite_int64 iDummy;
83 - int n = getVarint(pReader->pData, &iDummy);
84 + int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement);
85 + if( !n ) return NULL;
86 assert( !dlrAtEnd(pReader) );
87 return pReader->pData+n;
89 @@ -673,7 +685,7 @@ static int dlrPosDataLen(DLReader *pReader){
90 assert( !dlrAtEnd(pReader) );
91 return pReader->nElement-n;
93 -static void dlrStep(DLReader *pReader){
94 +static int dlrStep(DLReader *pReader){
95 assert( !dlrAtEnd(pReader) );
97 /* Skip past current doclist element. */
98 @@ -682,32 +694,48 @@ static void dlrStep(DLReader *pReader){
99 pReader->nData -= pReader->nElement;
101 /* If there is more data, read the next doclist element. */
102 - if( pReader->nData!=0 ){
103 + if( pReader->nData>0 ){
104 sqlite_int64 iDocidDelta;
105 - int iDummy, n = getVarint(pReader->pData, &iDocidDelta);
106 + int nTotal = 0;
107 + int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData);
108 + if( !n ) return SQLITE_CORRUPT_BKPT;
109 + nTotal += n;
110 pReader->iDocid += iDocidDelta;
111 if( pReader->iType>=DL_POSITIONS ){
112 - assert( n<pReader->nData );
113 while( 1 ){
114 - n += getVarint32(pReader->pData+n, &iDummy);
115 - assert( n<=pReader->nData );
116 + n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
117 + pReader->nData-nTotal);
118 + if( !n ) return SQLITE_CORRUPT_BKPT;
119 + nTotal += n;
120 if( iDummy==POS_END ) break;
121 if( iDummy==POS_COLUMN ){
122 - n += getVarint32(pReader->pData+n, &iDummy);
123 - assert( n<pReader->nData );
124 + n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
125 + pReader->nData-nTotal);
126 + if( !n ) return SQLITE_CORRUPT_BKPT;
127 + nTotal += n;
128 }else if( pReader->iType==DL_POSITIONS_OFFSETS ){
129 - n += getVarint32(pReader->pData+n, &iDummy);
130 - n += getVarint32(pReader->pData+n, &iDummy);
131 - assert( n<pReader->nData );
132 + n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
133 + pReader->nData-nTotal);
134 + if( !n ) return SQLITE_CORRUPT_BKPT;
135 + nTotal += n;
136 + n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
137 + pReader->nData-nTotal);
138 + if( !n ) return SQLITE_CORRUPT_BKPT;
139 + nTotal += n;
143 - pReader->nElement = n;
144 + pReader->nElement = nTotal;
145 assert( pReader->nElement<=pReader->nData );
147 + return SQLITE_OK;
149 -static void dlrInit(DLReader *pReader, DocListType iType,
150 - const char *pData, int nData){
151 +static void dlrDestroy(DLReader *pReader){
152 + SCRAMBLE(pReader);
154 +static int dlrInit(DLReader *pReader, DocListType iType,
155 + const char *pData, int nData){
156 + int rc;
157 assert( pData!=NULL && nData!=0 );
158 pReader->iType = iType;
159 pReader->pData = pData;
160 @@ -716,10 +744,9 @@ static void dlrInit(DLReader *pReader, DocListType iType,
161 pReader->iDocid = 0;
163 /* Load the first element's data. There must be a first element. */
164 - dlrStep(pReader);
166 -static void dlrDestroy(DLReader *pReader){
167 - SCRAMBLE(pReader);
168 + rc = dlrStep(pReader);
169 + if( rc!=SQLITE_OK ) dlrDestroy(pReader);
170 + return rc;
173 #ifndef NDEBUG
174 @@ -806,9 +833,9 @@ static void dlwDestroy(DLWriter *pWriter){
175 /* TODO(shess) This has become just a helper for docListMerge.
176 ** Consider a refactor to make this cleaner.
178 -static void dlwAppend(DLWriter *pWriter,
179 - const char *pData, int nData,
180 - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
181 +static int dlwAppend(DLWriter *pWriter,
182 + const char *pData, int nData,
183 + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
184 sqlite_int64 iDocid = 0;
185 char c[VARINT_MAX];
186 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */
187 @@ -817,7 +844,8 @@ static void dlwAppend(DLWriter *pWriter,
188 #endif
190 /* Recode the initial docid as delta from iPrevDocid. */
191 - nFirstOld = getVarint(pData, &iDocid);
192 + nFirstOld = getVarintSafe(pData, &iDocid, nData);
193 + if( !nFirstOld ) return SQLITE_CORRUPT_BKPT;
194 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
195 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);
197 @@ -838,10 +866,11 @@ static void dlwAppend(DLWriter *pWriter,
198 dataBufferAppend(pWriter->b, c, nFirstNew);
200 pWriter->iPrevDocid = iLastDocid;
201 + return SQLITE_OK;
203 -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){
204 - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
205 - dlrDocid(pReader), dlrDocid(pReader));
206 +static int dlwCopy(DLWriter *pWriter, DLReader *pReader){
207 + return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
208 + dlrDocid(pReader), dlrDocid(pReader));
210 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
211 char c[VARINT_MAX];
212 @@ -902,45 +931,63 @@ static int plrEndOffset(PLReader *pReader){
213 assert( !plrAtEnd(pReader) );
214 return pReader->iEndOffset;
216 -static void plrStep(PLReader *pReader){
217 - int i, n;
218 +static int plrStep(PLReader *pReader){
219 + int i, n, nTotal = 0;
221 assert( !plrAtEnd(pReader) );
223 - if( pReader->nData==0 ){
224 + if( pReader->nData<=0 ){
225 pReader->pData = NULL;
226 - return;
227 + return SQLITE_OK;
230 - n = getVarint32(pReader->pData, &i);
231 + n = getVarint32Safe(pReader->pData, &i, pReader->nData);
232 + if( !n ) return SQLITE_CORRUPT_BKPT;
233 + nTotal += n;
234 if( i==POS_COLUMN ){
235 - n += getVarint32(pReader->pData+n, &pReader->iColumn);
236 + n = getVarint32Safe(pReader->pData+nTotal, &pReader->iColumn,
237 + pReader->nData-nTotal);
238 + if( !n ) return SQLITE_CORRUPT_BKPT;
239 + nTotal += n;
240 pReader->iPosition = 0;
241 pReader->iStartOffset = 0;
242 - n += getVarint32(pReader->pData+n, &i);
243 + n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
244 + if( !n ) return SQLITE_CORRUPT_BKPT;
245 + nTotal += n;
247 /* Should never see adjacent column changes. */
248 assert( i!=POS_COLUMN );
250 if( i==POS_END ){
251 + assert( nTotal<=pReader->nData );
252 pReader->nData = 0;
253 pReader->pData = NULL;
254 - return;
255 + return SQLITE_OK;
258 pReader->iPosition += i-POS_BASE;
259 if( pReader->iType==DL_POSITIONS_OFFSETS ){
260 - n += getVarint32(pReader->pData+n, &i);
261 + n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
262 + if( !n ) return SQLITE_CORRUPT_BKPT;
263 + nTotal += n;
264 pReader->iStartOffset += i;
265 - n += getVarint32(pReader->pData+n, &i);
266 + n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
267 + if( !n ) return SQLITE_CORRUPT_BKPT;
268 + nTotal += n;
269 pReader->iEndOffset = pReader->iStartOffset+i;
271 - assert( n<=pReader->nData );
272 - pReader->pData += n;
273 - pReader->nData -= n;
274 + assert( nTotal<=pReader->nData );
275 + pReader->pData += nTotal;
276 + pReader->nData -= nTotal;
277 + return SQLITE_OK;
280 -static void plrInit(PLReader *pReader, DLReader *pDLReader){
281 +static void plrDestroy(PLReader *pReader){
282 + SCRAMBLE(pReader);
285 +static int plrInit(PLReader *pReader, DLReader *pDLReader){
286 + int rc;
287 pReader->pData = dlrPosData(pDLReader);
288 pReader->nData = dlrPosDataLen(pDLReader);
289 pReader->iType = pDLReader->iType;
290 @@ -948,10 +995,9 @@ static void plrInit(PLReader *pReader, DLReader *pDLReader){
291 pReader->iPosition = 0;
292 pReader->iStartOffset = 0;
293 pReader->iEndOffset = 0;
294 - plrStep(pReader);
296 -static void plrDestroy(PLReader *pReader){
297 - SCRAMBLE(pReader);
298 + rc = plrStep(pReader);
299 + if( rc!=SQLITE_OK ) plrDestroy(pReader);
300 + return rc;
303 /*******************************************************************/
304 @@ -1137,14 +1183,16 @@ static void dlcDelete(DLCollector *pCollector){
305 ** deletion will be trimmed, and will thus not effect a deletion
306 ** during the merge.
308 -static void docListTrim(DocListType iType, const char *pData, int nData,
309 - int iColumn, DocListType iOutType, DataBuffer *out){
310 +static int docListTrim(DocListType iType, const char *pData, int nData,
311 + int iColumn, DocListType iOutType, DataBuffer *out){
312 DLReader dlReader;
313 DLWriter dlWriter;
314 + int rc;
316 assert( iOutType<=iType );
318 - dlrInit(&dlReader, iType, pData, nData);
319 + rc = dlrInit(&dlReader, iType, pData, nData);
320 + if( rc!=SQLITE_OK ) return rc;
321 dlwInit(&dlWriter, iOutType, out);
323 while( !dlrAtEnd(&dlReader) ){
324 @@ -1152,7 +1200,8 @@ static void docListTrim(DocListType iType, const char *pData, int nData,
325 PLWriter plWriter;
326 int match = 0;
328 - plrInit(&plReader, &dlReader);
329 + rc = plrInit(&plReader, &dlReader);
330 + if( rc!=SQLITE_OK ) break;
332 while( !plrAtEnd(&plReader) ){
333 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
334 @@ -1163,7 +1212,11 @@ static void docListTrim(DocListType iType, const char *pData, int nData,
335 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
336 plrStartOffset(&plReader), plrEndOffset(&plReader));
338 - plrStep(&plReader);
339 + rc = plrStep(&plReader);
340 + if( rc!=SQLITE_OK ){
341 + plrDestroy(&plReader);
342 + goto err;
345 if( match ){
346 plwTerminate(&plWriter);
347 @@ -1171,10 +1224,13 @@ static void docListTrim(DocListType iType, const char *pData, int nData,
350 plrDestroy(&plReader);
351 - dlrStep(&dlReader);
352 + rc = dlrStep(&dlReader);
353 + if( rc!=SQLITE_OK ) break;
355 +err:
356 dlwDestroy(&dlWriter);
357 dlrDestroy(&dlReader);
358 + return rc;
361 /* Used by docListMerge() to keep doclists in the ascending order by
362 @@ -1231,19 +1287,20 @@ static void orderedDLReaderReorder(OrderedDLReader *p, int n){
363 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably
364 ** be fixed.
366 -static void docListMerge(DataBuffer *out,
367 - DLReader *pReaders, int nReaders){
368 +static int docListMerge(DataBuffer *out,
369 + DLReader *pReaders, int nReaders){
370 OrderedDLReader readers[MERGE_COUNT];
371 DLWriter writer;
372 int i, n;
373 const char *pStart = 0;
374 int nStart = 0;
375 sqlite_int64 iFirstDocid = 0, iLastDocid = 0;
376 + int rc = SQLITE_OK;
378 assert( nReaders>0 );
379 if( nReaders==1 ){
380 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
381 - return;
382 + return SQLITE_OK;
385 assert( nReaders<=MERGE_COUNT );
386 @@ -1276,20 +1333,23 @@ static void docListMerge(DataBuffer *out,
387 nStart += dlrDocDataBytes(readers[0].pReader);
388 }else{
389 if( pStart!=0 ){
390 - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
391 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
392 + if( rc!=SQLITE_OK ) goto err;
394 pStart = dlrDocData(readers[0].pReader);
395 nStart = dlrDocDataBytes(readers[0].pReader);
396 iFirstDocid = iDocid;
398 iLastDocid = iDocid;
399 - dlrStep(readers[0].pReader);
400 + rc = dlrStep(readers[0].pReader);
401 + if( rc!=SQLITE_OK ) goto err;
403 /* Drop all of the older elements with the same docid. */
404 for(i=1; i<nReaders &&
405 !dlrAtEnd(readers[i].pReader) &&
406 dlrDocid(readers[i].pReader)==iDocid; i++){
407 - dlrStep(readers[i].pReader);
408 + rc = dlrStep(readers[i].pReader);
409 + if( rc!=SQLITE_OK ) goto err;
412 /* Get the readers back into order. */
413 @@ -1299,8 +1359,11 @@ static void docListMerge(DataBuffer *out,
416 /* Copy over any remaining elements. */
417 - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
418 + if( nStart>0 )
419 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
420 +err:
421 dlwDestroy(&writer);
422 + return rc;
425 /* Helper function for posListUnion(). Compares the current position
426 @@ -1336,30 +1399,40 @@ static int posListCmp(PLReader *pLeft, PLReader *pRight){
427 ** work with any doclist type, though both inputs and the output
428 ** should be the same type.
430 -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
431 +static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
432 PLReader left, right;
433 PLWriter writer;
434 + int rc;
436 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
437 assert( pLeft->iType==pRight->iType );
438 assert( pLeft->iType==pOut->iType );
440 - plrInit(&left, pLeft);
441 - plrInit(&right, pRight);
442 + rc = plrInit(&left, pLeft);
443 + if( rc != SQLITE_OK ) return rc;
444 + rc = plrInit(&right, pRight);
445 + if( rc != SQLITE_OK ){
446 + plrDestroy(&left);
447 + return rc;
449 plwInit(&writer, pOut, dlrDocid(pLeft));
451 while( !plrAtEnd(&left) || !plrAtEnd(&right) ){
452 int c = posListCmp(&left, &right);
453 if( c<0 ){
454 plwCopy(&writer, &left);
455 - plrStep(&left);
456 + rc = plrStep(&left);
457 + if( rc != SQLITE_OK ) break;
458 }else if( c>0 ){
459 plwCopy(&writer, &right);
460 - plrStep(&right);
461 + rc = plrStep(&right);
462 + if( rc != SQLITE_OK ) break;
463 }else{
464 plwCopy(&writer, &left);
465 - plrStep(&left);
466 - plrStep(&right);
467 + rc = plrStep(&left);
468 + if( rc != SQLITE_OK ) break;
469 + rc = plrStep(&right);
470 + if( rc != SQLITE_OK ) break;
474 @@ -1367,56 +1440,75 @@ static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
475 plwDestroy(&writer);
476 plrDestroy(&left);
477 plrDestroy(&right);
478 + return rc;
481 /* Write the union of doclists in pLeft and pRight to pOut. For
482 ** docids in common between the inputs, the union of the position
483 ** lists is written. Inputs and outputs are always type DL_DEFAULT.
485 -static void docListUnion(
486 +static int docListUnion(
487 const char *pLeft, int nLeft,
488 const char *pRight, int nRight,
489 DataBuffer *pOut /* Write the combined doclist here */
491 DLReader left, right;
492 DLWriter writer;
493 + int rc;
495 if( nLeft==0 ){
496 if( nRight!=0) dataBufferAppend(pOut, pRight, nRight);
497 - return;
498 + return SQLITE_OK;
500 if( nRight==0 ){
501 dataBufferAppend(pOut, pLeft, nLeft);
502 - return;
503 + return SQLITE_OK;
506 - dlrInit(&left, DL_DEFAULT, pLeft, nLeft);
507 - dlrInit(&right, DL_DEFAULT, pRight, nRight);
508 + rc = dlrInit(&left, DL_DEFAULT, pLeft, nLeft);
509 + if( rc!=SQLITE_OK ) return rc;
510 + rc = dlrInit(&right, DL_DEFAULT, pRight, nRight);
511 + if( rc!=SQLITE_OK ){
512 + dlrDestroy(&left);
513 + return rc;
515 dlwInit(&writer, DL_DEFAULT, pOut);
517 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
518 if( dlrAtEnd(&right) ){
519 - dlwCopy(&writer, &left);
520 - dlrStep(&left);
521 + rc = dlwCopy(&writer, &left);
522 + if( rc!=SQLITE_OK ) break;
523 + rc = dlrStep(&left);
524 + if( rc!=SQLITE_OK ) break;
525 }else if( dlrAtEnd(&left) ){
526 - dlwCopy(&writer, &right);
527 - dlrStep(&right);
528 + rc = dlwCopy(&writer, &right);
529 + if( rc!=SQLITE_OK ) break;
530 + rc = dlrStep(&right);
531 + if( rc!=SQLITE_OK ) break;
532 }else if( dlrDocid(&left)<dlrDocid(&right) ){
533 - dlwCopy(&writer, &left);
534 - dlrStep(&left);
535 + rc = dlwCopy(&writer, &left);
536 + if( rc!=SQLITE_OK ) break;
537 + rc = dlrStep(&left);
538 + if( rc!=SQLITE_OK ) break;
539 }else if( dlrDocid(&left)>dlrDocid(&right) ){
540 - dlwCopy(&writer, &right);
541 - dlrStep(&right);
542 + rc = dlwCopy(&writer, &right);
543 + if( rc!=SQLITE_OK ) break;
544 + rc = dlrStep(&right);
545 + if( rc!=SQLITE_OK ) break;
546 }else{
547 - posListUnion(&left, &right, &writer);
548 - dlrStep(&left);
549 - dlrStep(&right);
550 + rc = posListUnion(&left, &right, &writer);
551 + if( rc!=SQLITE_OK ) break;
552 + rc = dlrStep(&left);
553 + if( rc!=SQLITE_OK ) break;
554 + rc = dlrStep(&right);
555 + if( rc!=SQLITE_OK ) break;
559 dlrDestroy(&left);
560 dlrDestroy(&right);
561 dlwDestroy(&writer);
562 + return rc;
565 /* pLeft and pRight are DLReaders positioned to the same docid.
566 @@ -1431,35 +1523,47 @@ static void docListUnion(
567 ** include the positions from pRight that are one more than a
568 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
570 -static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
571 - DLWriter *pOut){
572 +static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
573 + DLWriter *pOut){
574 PLReader left, right;
575 PLWriter writer;
576 int match = 0;
577 + int rc;
579 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
580 assert( pOut->iType!=DL_POSITIONS_OFFSETS );
582 - plrInit(&left, pLeft);
583 - plrInit(&right, pRight);
584 + rc = plrInit(&left, pLeft);
585 + if( rc!=SQLITE_OK ) return rc;
586 + rc = plrInit(&right, pRight);
587 + if( rc!=SQLITE_OK ){
588 + plrDestroy(&left);
589 + return rc;
592 while( !plrAtEnd(&left) && !plrAtEnd(&right) ){
593 if( plrColumn(&left)<plrColumn(&right) ){
594 - plrStep(&left);
595 + rc = plrStep(&left);
596 + if( rc!=SQLITE_OK ) break;
597 }else if( plrColumn(&left)>plrColumn(&right) ){
598 - plrStep(&right);
599 + rc = plrStep(&right);
600 + if( rc!=SQLITE_OK ) break;
601 }else if( plrPosition(&left)+1<plrPosition(&right) ){
602 - plrStep(&left);
603 + rc = plrStep(&left);
604 + if( rc!=SQLITE_OK ) break;
605 }else if( plrPosition(&left)+1>plrPosition(&right) ){
606 - plrStep(&right);
607 + rc = plrStep(&right);
608 + if( rc!=SQLITE_OK ) break;
609 }else{
610 if( !match ){
611 plwInit(&writer, pOut, dlrDocid(pLeft));
612 match = 1;
614 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
615 - plrStep(&left);
616 - plrStep(&right);
617 + rc = plrStep(&left);
618 + if( rc!=SQLITE_OK ) break;
619 + rc = plrStep(&right);
620 + if( rc!=SQLITE_OK ) break;
624 @@ -1470,6 +1574,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
626 plrDestroy(&left);
627 plrDestroy(&right);
628 + return rc;
631 /* We have two doclists with positions: pLeft and pRight.
632 @@ -1481,7 +1586,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
633 ** iType controls the type of data written to pOut. If iType is
634 ** DL_POSITIONS, the positions are those from pRight.
636 -static void docListPhraseMerge(
637 +static int docListPhraseMerge(
638 const char *pLeft, int nLeft,
639 const char *pRight, int nRight,
640 DocListType iType,
641 @@ -1489,152 +1594,198 @@ static void docListPhraseMerge(
643 DLReader left, right;
644 DLWriter writer;
645 + int rc;
647 - if( nLeft==0 || nRight==0 ) return;
648 + if( nLeft==0 || nRight==0 ) return SQLITE_OK;
650 assert( iType!=DL_POSITIONS_OFFSETS );
652 - dlrInit(&left, DL_POSITIONS, pLeft, nLeft);
653 - dlrInit(&right, DL_POSITIONS, pRight, nRight);
654 + rc = dlrInit(&left, DL_POSITIONS, pLeft, nLeft);
655 + if( rc!=SQLITE_OK ) return rc;
656 + rc = dlrInit(&right, DL_POSITIONS, pRight, nRight);
657 + if( rc!=SQLITE_OK ){
658 + dlrDestroy(&left);
659 + return rc;
661 dlwInit(&writer, iType, pOut);
663 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
664 if( dlrDocid(&left)<dlrDocid(&right) ){
665 - dlrStep(&left);
666 + rc = dlrStep(&left);
667 + if( rc!=SQLITE_OK ) break;
668 }else if( dlrDocid(&right)<dlrDocid(&left) ){
669 - dlrStep(&right);
670 + rc = dlrStep(&right);
671 + if( rc!=SQLITE_OK ) break;
672 }else{
673 - posListPhraseMerge(&left, &right, &writer);
674 - dlrStep(&left);
675 - dlrStep(&right);
676 + rc = posListPhraseMerge(&left, &right, &writer);
677 + if( rc!=SQLITE_OK ) break;
678 + rc = dlrStep(&left);
679 + if( rc!=SQLITE_OK ) break;
680 + rc = dlrStep(&right);
681 + if( rc!=SQLITE_OK ) break;
685 dlrDestroy(&left);
686 dlrDestroy(&right);
687 dlwDestroy(&writer);
688 + return rc;
691 /* We have two DL_DOCIDS doclists: pLeft and pRight.
692 ** Write the intersection of these two doclists into pOut as a
693 ** DL_DOCIDS doclist.
695 -static void docListAndMerge(
696 +static int docListAndMerge(
697 const char *pLeft, int nLeft,
698 const char *pRight, int nRight,
699 DataBuffer *pOut /* Write the combined doclist here */
701 DLReader left, right;
702 DLWriter writer;
703 + int rc;
705 - if( nLeft==0 || nRight==0 ) return;
706 + if( nLeft==0 || nRight==0 ) return SQLITE_OK;
708 - dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
709 - dlrInit(&right, DL_DOCIDS, pRight, nRight);
710 + rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
711 + if( rc!=SQLITE_OK ) return rc;
712 + rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
713 + if( rc!=SQLITE_OK ){
714 + dlrDestroy(&left);
715 + return rc;
717 dlwInit(&writer, DL_DOCIDS, pOut);
719 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
720 if( dlrDocid(&left)<dlrDocid(&right) ){
721 - dlrStep(&left);
722 + rc = dlrStep(&left);
723 + if( rc!=SQLITE_OK ) break;
724 }else if( dlrDocid(&right)<dlrDocid(&left) ){
725 - dlrStep(&right);
726 + rc = dlrStep(&right);
727 + if( rc!=SQLITE_OK ) break;
728 }else{
729 dlwAdd(&writer, dlrDocid(&left));
730 - dlrStep(&left);
731 - dlrStep(&right);
732 + rc = dlrStep(&left);
733 + if( rc!=SQLITE_OK ) break;
734 + rc = dlrStep(&right);
735 + if( rc!=SQLITE_OK ) break;
739 dlrDestroy(&left);
740 dlrDestroy(&right);
741 dlwDestroy(&writer);
742 + return rc;
745 /* We have two DL_DOCIDS doclists: pLeft and pRight.
746 ** Write the union of these two doclists into pOut as a
747 ** DL_DOCIDS doclist.
749 -static void docListOrMerge(
750 +static int docListOrMerge(
751 const char *pLeft, int nLeft,
752 const char *pRight, int nRight,
753 DataBuffer *pOut /* Write the combined doclist here */
755 DLReader left, right;
756 DLWriter writer;
757 + int rc;
759 if( nLeft==0 ){
760 if( nRight!=0 ) dataBufferAppend(pOut, pRight, nRight);
761 - return;
762 + return SQLITE_OK;
764 if( nRight==0 ){
765 dataBufferAppend(pOut, pLeft, nLeft);
766 - return;
767 + return SQLITE_OK;
770 - dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
771 - dlrInit(&right, DL_DOCIDS, pRight, nRight);
772 + rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
773 + if( rc!=SQLITE_OK ) return rc;
774 + rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
775 + if( rc!=SQLITE_OK ){
776 + dlrDestroy(&left);
777 + return rc;
779 dlwInit(&writer, DL_DOCIDS, pOut);
781 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
782 if( dlrAtEnd(&right) ){
783 dlwAdd(&writer, dlrDocid(&left));
784 - dlrStep(&left);
785 + rc = dlrStep(&left);
786 + if( rc!=SQLITE_OK ) break;
787 }else if( dlrAtEnd(&left) ){
788 dlwAdd(&writer, dlrDocid(&right));
789 - dlrStep(&right);
790 + rc = dlrStep(&right);
791 + if( rc!=SQLITE_OK ) break;
792 }else if( dlrDocid(&left)<dlrDocid(&right) ){
793 dlwAdd(&writer, dlrDocid(&left));
794 - dlrStep(&left);
795 + rc = dlrStep(&left);
796 + if( rc!=SQLITE_OK ) break;
797 }else if( dlrDocid(&right)<dlrDocid(&left) ){
798 dlwAdd(&writer, dlrDocid(&right));
799 - dlrStep(&right);
800 + rc = dlrStep(&right);
801 + if( rc!=SQLITE_OK ) break;
802 }else{
803 dlwAdd(&writer, dlrDocid(&left));
804 - dlrStep(&left);
805 - dlrStep(&right);
806 + rc = dlrStep(&left);
807 + if( rc!=SQLITE_OK ) break;
808 + rc = dlrStep(&right);
809 + if( rc!=SQLITE_OK ) break;
813 dlrDestroy(&left);
814 dlrDestroy(&right);
815 dlwDestroy(&writer);
816 + return rc;
819 /* We have two DL_DOCIDS doclists: pLeft and pRight.
820 ** Write into pOut as DL_DOCIDS doclist containing all documents that
821 ** occur in pLeft but not in pRight.
823 -static void docListExceptMerge(
824 +static int docListExceptMerge(
825 const char *pLeft, int nLeft,
826 const char *pRight, int nRight,
827 DataBuffer *pOut /* Write the combined doclist here */
829 DLReader left, right;
830 DLWriter writer;
831 + int rc;
833 - if( nLeft==0 ) return;
834 + if( nLeft==0 ) return SQLITE_OK;
835 if( nRight==0 ){
836 dataBufferAppend(pOut, pLeft, nLeft);
837 - return;
838 + return SQLITE_OK;
841 - dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
842 - dlrInit(&right, DL_DOCIDS, pRight, nRight);
843 + rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
844 + if( rc!=SQLITE_OK ) return rc;
845 + rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
846 + if( rc!=SQLITE_OK ){
847 + dlrDestroy(&left);
848 + return rc;
850 dlwInit(&writer, DL_DOCIDS, pOut);
852 while( !dlrAtEnd(&left) ){
853 while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){
854 - dlrStep(&right);
855 + rc = dlrStep(&right);
856 + if( rc!=SQLITE_OK ) goto err;
858 if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){
859 dlwAdd(&writer, dlrDocid(&left));
861 - dlrStep(&left);
862 + rc = dlrStep(&left);
863 + if( rc!=SQLITE_OK ) break;
866 +err:
867 dlrDestroy(&left);
868 dlrDestroy(&right);
869 dlwDestroy(&writer);
870 + return rc;
873 static char *string_dup_n(const char *s, int n){
874 @@ -3437,7 +3588,8 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){
875 return SQLITE_OK;
877 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
878 - dlrStep(&c->reader);
879 + if( rc!=SQLITE_OK ) return rc;
880 + rc = dlrStep(&c->reader);
881 if( rc!=SQLITE_OK ) return rc;
882 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
883 rc = sqlite3_step(c->pStmt);
884 @@ -3497,14 +3649,18 @@ static int docListOfTerm(
885 return rc;
887 dataBufferInit(&new, 0);
888 - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
889 - i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
890 + rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
891 + i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
892 dataBufferDestroy(&left);
893 dataBufferDestroy(&right);
894 + if( rc!=SQLITE_OK ){
895 + dataBufferDestroy(&new);
896 + return rc;
898 left = new;
900 *pResult = left;
901 - return SQLITE_OK;
902 + return rc;
905 /* Add a new term pTerm[0..nTerm-1] to the query *q.
906 @@ -3749,18 +3905,30 @@ static int fulltextQuery(
907 return rc;
909 dataBufferInit(&new, 0);
910 - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
911 + rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
912 dataBufferDestroy(&right);
913 dataBufferDestroy(&or);
914 + if( rc!=SQLITE_OK ){
915 + if( i!=nNot ) dataBufferDestroy(&left);
916 + queryClear(pQuery);
917 + dataBufferDestroy(&new);
918 + return rc;
920 right = new;
922 if( i==nNot ){ /* first term processed. */
923 left = right;
924 }else{
925 dataBufferInit(&new, 0);
926 - docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new);
927 + rc = docListAndMerge(left.pData, left.nData,
928 + right.pData, right.nData, &new);
929 dataBufferDestroy(&right);
930 dataBufferDestroy(&left);
931 + if( rc!=SQLITE_OK ){
932 + queryClear(pQuery);
933 + dataBufferDestroy(&new);
934 + return rc;
936 left = new;
939 @@ -3780,9 +3948,15 @@ static int fulltextQuery(
940 return rc;
942 dataBufferInit(&new, 0);
943 - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new);
944 + rc = docListExceptMerge(left.pData, left.nData,
945 + right.pData, right.nData, &new);
946 dataBufferDestroy(&right);
947 dataBufferDestroy(&left);
948 + if( rc!=SQLITE_OK ){
949 + queryClear(pQuery);
950 + dataBufferDestroy(&new);
951 + return rc;
953 left = new;
956 @@ -3876,7 +4050,8 @@ static int fulltextFilter(
957 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q);
958 if( rc!=SQLITE_OK ) return rc;
959 if( c->result.nData!=0 ){
960 - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
961 + rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
962 + if( rc!=SQLITE_OK ) return rc;
964 break;
966 @@ -4377,22 +4552,19 @@ static void interiorReaderDestroy(InteriorReader *pReader){
967 SCRAMBLE(pReader);
970 -/* TODO(shess) The assertions are great, but what if we're in NDEBUG
971 -** and the blob is empty or otherwise contains suspect data?
973 -static void interiorReaderInit(const char *pData, int nData,
974 - InteriorReader *pReader){
975 +static int interiorReaderInit(const char *pData, int nData,
976 + InteriorReader *pReader){
977 int n, nTerm;
979 - /* Require at least the leading flag byte */
980 + /* These conditions are checked and met by the callers. */
981 assert( nData>0 );
982 assert( pData[0]!='\0' );
984 CLEAR(pReader);
986 /* Decode the base blockid, and set the cursor to the first term. */
987 - n = getVarint(pData+1, &pReader->iBlockid);
988 - assert( 1+n<=nData );
989 + n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1);
990 + if( !n ) return SQLITE_CORRUPT_BKPT;
991 pReader->pData = pData+1+n;
992 pReader->nData = nData-(1+n);
994 @@ -4403,17 +4575,18 @@ static void interiorReaderInit(const char *pData, int nData,
995 if( pReader->nData==0 ){
996 dataBufferInit(&pReader->term, 0);
997 }else{
998 - n = getVarint32(pReader->pData, &nTerm);
999 + n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData);
1000 + if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT;
1001 dataBufferInit(&pReader->term, nTerm);
1002 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
1003 - assert( n+nTerm<=pReader->nData );
1004 pReader->pData += n+nTerm;
1005 pReader->nData -= n+nTerm;
1007 + return SQLITE_OK;
1010 static int interiorReaderAtEnd(InteriorReader *pReader){
1011 - return pReader->term.nData==0;
1012 + return pReader->term.nData<=0;
1015 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
1016 @@ -4430,7 +4603,7 @@ static const char *interiorReaderTerm(InteriorReader *pReader){
1019 /* Step forward to the next term in the node. */
1020 -static void interiorReaderStep(InteriorReader *pReader){
1021 +static int interiorReaderStep(InteriorReader *pReader){
1022 assert( !interiorReaderAtEnd(pReader) );
1024 /* If the last term has been read, signal eof, else construct the
1025 @@ -4441,18 +4614,26 @@ static void interiorReaderStep(InteriorReader *pReader){
1026 }else{
1027 int n, nPrefix, nSuffix;
1029 - n = getVarint32(pReader->pData, &nPrefix);
1030 - n += getVarint32(pReader->pData+n, &nSuffix);
1031 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1032 + if( !n ) return SQLITE_CORRUPT_BKPT;
1033 + pReader->nData -= n;
1034 + pReader->pData += n;
1035 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
1036 + if( !n ) return SQLITE_CORRUPT_BKPT;
1037 + pReader->nData -= n;
1038 + pReader->pData += n;
1039 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
1040 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
1042 /* Truncate the current term and append suffix data. */
1043 pReader->term.nData = nPrefix;
1044 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
1045 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
1047 - assert( n+nSuffix<=pReader->nData );
1048 - pReader->pData += n+nSuffix;
1049 - pReader->nData -= n+nSuffix;
1050 + pReader->pData += nSuffix;
1051 + pReader->nData -= nSuffix;
1053 pReader->iBlockid++;
1054 + return SQLITE_OK;
1057 /* Compare the current term to pTerm[nTerm], returning strcmp-style
1058 @@ -4824,7 +5005,8 @@ static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter,
1059 n = putVarint(c, nData);
1060 dataBufferAppend(&pWriter->data, c, n);
1062 - docListMerge(&pWriter->data, pReaders, nReaders);
1063 + rc = docListMerge(&pWriter->data, pReaders, nReaders);
1064 + if( rc!= SQLITE_OK ) return rc;
1065 ASSERT_VALID_DOCLIST(DL_DEFAULT,
1066 pWriter->data.pData+iDoclistData+n,
1067 pWriter->data.nData-iDoclistData-n, NULL);
1068 @@ -4934,7 +5116,8 @@ static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter,
1069 int rc;
1070 DLReader reader;
1072 - dlrInit(&reader, DL_DEFAULT, pData, nData);
1073 + rc = dlrInit(&reader, DL_DEFAULT, pData, nData);
1074 + if( rc!=SQLITE_OK ) return rc;
1075 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
1076 dlrDestroy(&reader);
1078 @@ -4979,38 +5162,40 @@ static int leafReaderDataBytes(LeafReader *pReader){
1079 static const char *leafReaderData(LeafReader *pReader){
1080 int n, nData;
1081 assert( pReader->term.nData>0 );
1082 - n = getVarint32(pReader->pData, &nData);
1083 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1084 + if( !n || nData>pReader->nData-n ) return NULL;
1085 return pReader->pData+n;
1088 -static void leafReaderInit(const char *pData, int nData,
1089 - LeafReader *pReader){
1090 +static int leafReaderInit(const char *pData, int nData, LeafReader *pReader){
1091 int nTerm, n;
1093 + /* All callers check this precondition. */
1094 assert( nData>0 );
1095 assert( pData[0]=='\0' );
1097 CLEAR(pReader);
1099 /* Read the first term, skipping the header byte. */
1100 - n = getVarint32(pData+1, &nTerm);
1101 + n = getVarint32Safe(pData+1, &nTerm, nData-1);
1102 + if( !n || nTerm<0 || nTerm>nData-1-n ) return SQLITE_CORRUPT_BKPT;
1103 dataBufferInit(&pReader->term, nTerm);
1104 dataBufferReplace(&pReader->term, pData+1+n, nTerm);
1106 /* Position after the first term. */
1107 - assert( 1+n+nTerm<nData );
1108 pReader->pData = pData+1+n+nTerm;
1109 pReader->nData = nData-1-n-nTerm;
1110 + return SQLITE_OK;
1113 /* Step the reader forward to the next term. */
1114 -static void leafReaderStep(LeafReader *pReader){
1115 +static int leafReaderStep(LeafReader *pReader){
1116 int n, nData, nPrefix, nSuffix;
1117 assert( !leafReaderAtEnd(pReader) );
1119 /* Skip previous entry's data block. */
1120 - n = getVarint32(pReader->pData, &nData);
1121 - assert( n+nData<=pReader->nData );
1122 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1123 + if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT;
1124 pReader->pData += n+nData;
1125 pReader->nData -= n+nData;
1127 @@ -5018,15 +5203,23 @@ static void leafReaderStep(LeafReader *pReader){
1128 /* Construct the new term using a prefix from the old term plus a
1129 ** suffix from the leaf data.
1131 - n = getVarint32(pReader->pData, &nPrefix);
1132 - n += getVarint32(pReader->pData+n, &nSuffix);
1133 - assert( n+nSuffix<pReader->nData );
1134 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1135 + if( !n ) return SQLITE_CORRUPT_BKPT;
1136 + pReader->nData -= n;
1137 + pReader->pData += n;
1138 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
1139 + if( !n ) return SQLITE_CORRUPT_BKPT;
1140 + pReader->nData -= n;
1141 + pReader->pData += n;
1142 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
1143 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
1144 pReader->term.nData = nPrefix;
1145 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
1146 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
1148 - pReader->pData += n+nSuffix;
1149 - pReader->nData -= n+nSuffix;
1150 + pReader->pData += nSuffix;
1151 + pReader->nData -= nSuffix;
1153 + return SQLITE_OK;
1156 /* strcmp-style comparison of pReader's current term against pTerm.
1157 @@ -5133,14 +5326,19 @@ static int leavesReaderInit(fulltext_vtab *v,
1159 dataBufferInit(&pReader->rootData, 0);
1160 if( iStartBlockid==0 ){
1161 + int rc;
1162 /* Corrupt if this can't be a leaf node. */
1163 if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){
1164 return SQLITE_CORRUPT_BKPT;
1166 /* Entire leaf level fit in root data. */
1167 dataBufferReplace(&pReader->rootData, pRootData, nRootData);
1168 - leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
1169 - &pReader->leafReader);
1170 + rc = leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
1171 + &pReader->leafReader);
1172 + if( rc!=SQLITE_OK ){
1173 + dataBufferDestroy(&pReader->rootData);
1174 + return rc;
1176 }else{
1177 sqlite3_stmt *s;
1178 int rc = sql_get_leaf_statement(v, idx, &s);
1179 @@ -5174,7 +5372,7 @@ static int leavesReaderInit(fulltext_vtab *v,
1180 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
1181 rc = SQLITE_CORRUPT_BKPT;
1182 }else{
1183 - leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1184 + rc = leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1188 @@ -5197,11 +5395,12 @@ static int leavesReaderInit(fulltext_vtab *v,
1189 ** end of the current leaf, step forward to the next leaf block.
1191 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1192 + int rc;
1193 assert( !leavesReaderAtEnd(pReader) );
1194 - leafReaderStep(&pReader->leafReader);
1195 + rc = leafReaderStep(&pReader->leafReader);
1196 + if( rc!=SQLITE_OK ) return rc;
1198 if( leafReaderAtEnd(&pReader->leafReader) ){
1199 - int rc;
1200 if( pReader->rootData.pData ){
1201 pReader->eof = 1;
1202 return SQLITE_OK;
1203 @@ -5216,6 +5415,7 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1204 if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
1205 return SQLITE_CORRUPT_BKPT;
1206 }else{
1207 + LeafReader tmp;
1208 const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0);
1209 int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0);
1211 @@ -5224,8 +5424,10 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1212 return SQLITE_CORRUPT_BKPT;
1215 + rc = leafReaderInit(pLeafData, nLeafData, &tmp);
1216 + if( rc!=SQLITE_OK ) return rc;
1217 leafReaderDestroy(&pReader->leafReader);
1218 - leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
1219 + pReader->leafReader = tmp;
1222 return SQLITE_OK;
1223 @@ -5334,13 +5536,26 @@ static int leavesReadersMerge(fulltext_vtab *v,
1224 DLReader dlReaders[MERGE_COUNT];
1225 const char *pTerm = leavesReaderTerm(pReaders);
1226 int i, nTerm = leavesReaderTermBytes(pReaders);
1227 + int rc;
1229 assert( nReaders<=MERGE_COUNT );
1231 for(i=0; i<nReaders; i++){
1232 - dlrInit(&dlReaders[i], DL_DEFAULT,
1233 - leavesReaderData(pReaders+i),
1234 - leavesReaderDataBytes(pReaders+i));
1235 + const char *pData = leavesReaderData(pReaders+i);
1236 + if( pData==NULL ){
1237 + rc = SQLITE_CORRUPT_BKPT;
1238 + break;
1240 + rc = dlrInit(&dlReaders[i], DL_DEFAULT,
1241 + pData,
1242 + leavesReaderDataBytes(pReaders+i));
1243 + if( rc!=SQLITE_OK ) break;
1245 + if( rc!=SQLITE_OK ){
1246 + while( i-->0 ){
1247 + dlrDestroy(&dlReaders[i]);
1249 + return rc;
1252 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
1253 @@ -5444,12 +5659,14 @@ static int segmentMerge(fulltext_vtab *v, int iLevel){
1256 /* Accumulate the union of *acc and *pData into *acc. */
1257 -static void docListAccumulateUnion(DataBuffer *acc,
1258 - const char *pData, int nData) {
1259 +static int docListAccumulateUnion(DataBuffer *acc,
1260 + const char *pData, int nData) {
1261 DataBuffer tmp = *acc;
1262 + int rc;
1263 dataBufferInit(acc, tmp.nData+nData);
1264 - docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1265 + rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1266 dataBufferDestroy(&tmp);
1267 + return rc;
1270 /* TODO(shess) It might be interesting to explore different merge
1271 @@ -5491,8 +5708,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader,
1272 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
1273 if( c>0 ) break; /* Past any possible matches. */
1274 if( c==0 ){
1275 + int iBuffer, nData;
1276 const char *pData = leavesReaderData(pReader);
1277 - int iBuffer, nData = leavesReaderDataBytes(pReader);
1278 + if( pData==NULL ){
1279 + rc = SQLITE_CORRUPT_BKPT;
1280 + break;
1282 + nData = leavesReaderDataBytes(pReader);
1284 /* Find the first empty buffer. */
1285 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
1286 @@ -5538,11 +5760,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader,
1287 ** with pData/nData.
1289 dataBufferSwap(p, pAcc);
1290 - docListAccumulateUnion(pAcc, pData, nData);
1291 + rc = docListAccumulateUnion(pAcc, pData, nData);
1292 + if( rc!=SQLITE_OK ) goto err;
1294 /* Accumulate remaining doclists into pAcc. */
1295 for(++p; p<pAcc; ++p){
1296 - docListAccumulateUnion(pAcc, p->pData, p->nData);
1297 + rc = docListAccumulateUnion(pAcc, p->pData, p->nData);
1298 + if( rc!=SQLITE_OK ) goto err;
1300 /* dataBufferReset() could allow a large doclist to blow up
1301 ** our memory requirements.
1302 @@ -5567,13 +5791,15 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader,
1303 if( out->nData==0 ){
1304 dataBufferSwap(out, &(pBuffers[iBuffer]));
1305 }else{
1306 - docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1307 - pBuffers[iBuffer].nData);
1308 + rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1309 + pBuffers[iBuffer].nData);
1310 + if( rc!=SQLITE_OK ) break;
1316 +err:
1317 while( nBuffers-- ){
1318 dataBufferDestroy(&(pBuffers[nBuffers]));
1320 @@ -5632,20 +5858,26 @@ static int loadSegmentLeaves(fulltext_vtab *v,
1321 ** node. Consider whether breaking symmetry is worthwhile. I suspect
1322 ** it is not worthwhile.
1324 -static void getChildrenContaining(const char *pData, int nData,
1325 - const char *pTerm, int nTerm, int isPrefix,
1326 - sqlite_int64 *piStartChild,
1327 - sqlite_int64 *piEndChild){
1328 +static int getChildrenContaining(const char *pData, int nData,
1329 + const char *pTerm, int nTerm, int isPrefix,
1330 + sqlite_int64 *piStartChild,
1331 + sqlite_int64 *piEndChild){
1332 InteriorReader reader;
1333 + int rc;
1335 assert( nData>1 );
1336 assert( *pData!='\0' );
1337 - interiorReaderInit(pData, nData, &reader);
1338 + rc = interiorReaderInit(pData, nData, &reader);
1339 + if( rc!=SQLITE_OK ) return rc;
1341 /* Scan for the first child which could contain pTerm/nTerm. */
1342 while( !interiorReaderAtEnd(&reader) ){
1343 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
1344 - interiorReaderStep(&reader);
1345 + rc = interiorReaderStep(&reader);
1346 + if( rc!=SQLITE_OK ){
1347 + interiorReaderDestroy(&reader);
1348 + return rc;
1351 *piStartChild = interiorReaderCurrentBlockid(&reader);
1353 @@ -5655,7 +5887,11 @@ static void getChildrenContaining(const char *pData, int nData,
1355 while( !interiorReaderAtEnd(&reader) ){
1356 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
1357 - interiorReaderStep(&reader);
1358 + rc = interiorReaderStep(&reader);
1359 + if( rc!=SQLITE_OK ){
1360 + interiorReaderDestroy(&reader);
1361 + return rc;
1364 *piEndChild = interiorReaderCurrentBlockid(&reader);
1366 @@ -5664,6 +5900,7 @@ static void getChildrenContaining(const char *pData, int nData,
1367 /* Children must ascend, and if !prefix, both must be the same. */
1368 assert( *piEndChild>=*piStartChild );
1369 assert( isPrefix || *piStartChild==*piEndChild );
1370 + return rc;
1373 /* Read block at iBlockid and pass it with other params to
1374 @@ -5709,8 +5946,12 @@ static int loadAndGetChildrenContaining(
1375 return SQLITE_CORRUPT_BKPT;
1378 - getChildrenContaining(pData, nData, pTerm, nTerm,
1379 - isPrefix, piStartChild, piEndChild);
1380 + rc = getChildrenContaining(pData, nData, pTerm, nTerm,
1381 + isPrefix, piStartChild, piEndChild);
1382 + if( rc!=SQLITE_OK ){
1383 + sqlite3_reset(s);
1384 + return rc;
1388 /* We expect only one row. We must execute another sqlite3_step()
1389 @@ -5741,8 +5982,9 @@ static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData,
1390 /* Process pData as an interior node, then loop down the tree
1391 ** until we find the set of leaf nodes to scan for the term.
1393 - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1394 - &iStartChild, &iEndChild);
1395 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1396 + &iStartChild, &iEndChild);
1397 + if( rc!=SQLITE_OK ) return rc;
1398 while( iStartChild>iLeavesEnd ){
1399 sqlite_int64 iNextStart, iNextEnd;
1400 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
1401 @@ -5812,16 +6054,21 @@ static int loadSegment(fulltext_vtab *v, const char *pData, int nData,
1402 DataBuffer merged;
1403 DLReader readers[2];
1405 - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1406 - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1407 - dataBufferInit(&merged, out->nData+result.nData);
1408 - docListMerge(&merged, readers, 2);
1409 - dataBufferDestroy(out);
1410 - *out = merged;
1411 - dlrDestroy(&readers[0]);
1412 - dlrDestroy(&readers[1]);
1413 + rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1414 + if( rc==SQLITE_OK ){
1415 + rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1416 + if( rc==SQLITE_OK ){
1417 + dataBufferInit(&merged, out->nData+result.nData);
1418 + rc = docListMerge(&merged, readers, 2);
1419 + dataBufferDestroy(out);
1420 + *out = merged;
1421 + dlrDestroy(&readers[1]);
1423 + dlrDestroy(&readers[0]);
1428 dataBufferDestroy(&result);
1429 return rc;
1431 @@ -5862,6 +6109,7 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1432 if( rc!=SQLITE_OK ) goto err;
1434 if( rc==SQLITE_DONE ){
1435 + rc = SQLITE_OK;
1436 if( doclist.nData!=0 ){
1437 /* TODO(shess) The old term_select_all() code applied the column
1438 ** restrict as we merged segments, leading to smaller buffers.
1439 @@ -5869,10 +6117,9 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1440 ** system is checked in.
1442 if( iColumn==v->nColumn) iColumn = -1;
1443 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1444 - iColumn, iType, out);
1445 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1446 + iColumn, iType, out);
1448 - rc = SQLITE_OK;
1451 err:
1452 @@ -6218,6 +6465,7 @@ static int optimizeInternal(fulltext_vtab *v,
1453 LeafWriter *pWriter){
1454 int i, rc = SQLITE_OK;
1455 DataBuffer doclist, merged, tmp;
1456 + const char *pData;
1458 /* Order the readers. */
1459 i = nReaders;
1460 @@ -6238,14 +6486,21 @@ static int optimizeInternal(fulltext_vtab *v,
1461 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
1464 + pData = optLeavesReaderData(&readers[0]);
1465 + if( pData==NULL ){
1466 + rc = SQLITE_CORRUPT_BKPT;
1467 + break;
1470 /* Special-case for no merge. */
1471 if( i==1 ){
1472 /* Trim deletions from the doclist. */
1473 dataBufferReset(&merged);
1474 - docListTrim(DL_DEFAULT,
1475 - optLeavesReaderData(&readers[0]),
1476 - optLeavesReaderDataBytes(&readers[0]),
1477 - -1, DL_DEFAULT, &merged);
1478 + rc = docListTrim(DL_DEFAULT,
1479 + pData,
1480 + optLeavesReaderDataBytes(&readers[0]),
1481 + -1, DL_DEFAULT, &merged);
1482 + if( rc!= SQLITE_OK ) break;
1483 }else{
1484 DLReader dlReaders[MERGE_COUNT];
1485 int iReader, nReaders;
1486 @@ -6253,9 +6508,10 @@ static int optimizeInternal(fulltext_vtab *v,
1487 /* Prime the pipeline with the first reader's doclist. After
1488 ** one pass index 0 will reference the accumulated doclist.
1490 - dlrInit(&dlReaders[0], DL_DEFAULT,
1491 - optLeavesReaderData(&readers[0]),
1492 - optLeavesReaderDataBytes(&readers[0]));
1493 + rc = dlrInit(&dlReaders[0], DL_DEFAULT,
1494 + pData,
1495 + optLeavesReaderDataBytes(&readers[0]));
1496 + if( rc!=SQLITE_OK ) break;
1497 iReader = 1;
1499 assert( iReader<i ); /* Must execute the loop at least once. */
1500 @@ -6263,24 +6519,35 @@ static int optimizeInternal(fulltext_vtab *v,
1501 /* Merge 16 inputs per pass. */
1502 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
1503 iReader++, nReaders++ ){
1504 - dlrInit(&dlReaders[nReaders], DL_DEFAULT,
1505 - optLeavesReaderData(&readers[iReader]),
1506 - optLeavesReaderDataBytes(&readers[iReader]));
1507 + pData = optLeavesReaderData(&readers[iReader]);
1508 + if( pData == NULL ){
1509 + rc = SQLITE_CORRUPT_BKPT;
1510 + break;
1512 + rc = dlrInit(&dlReaders[nReaders], DL_DEFAULT,
1513 + pData,
1514 + optLeavesReaderDataBytes(&readers[iReader]));
1515 + if( rc != SQLITE_OK ) break;
1518 /* Merge doclists and swap result into accumulator. */
1519 - dataBufferReset(&merged);
1520 - docListMerge(&merged, dlReaders, nReaders);
1521 - tmp = merged;
1522 - merged = doclist;
1523 - doclist = tmp;
1524 + if( rc==SQLITE_OK ){
1525 + dataBufferReset(&merged);
1526 + rc = docListMerge(&merged, dlReaders, nReaders);
1527 + tmp = merged;
1528 + merged = doclist;
1529 + doclist = tmp;
1532 while( nReaders-- > 0 ){
1533 dlrDestroy(&dlReaders[nReaders]);
1536 + if( rc!=SQLITE_OK ) goto err;
1538 /* Accumulated doclist to reader 0 for next pass. */
1539 - dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1540 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1541 + if( rc!=SQLITE_OK ) goto err;
1544 /* Destroy reader that was left in the pipeline. */
1545 @@ -6288,8 +6555,9 @@ static int optimizeInternal(fulltext_vtab *v,
1547 /* Trim deletions from the doclist. */
1548 dataBufferReset(&merged);
1549 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1550 - -1, DL_DEFAULT, &merged);
1551 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1552 + -1, DL_DEFAULT, &merged);
1553 + if( rc!=SQLITE_OK ) goto err;
1556 /* Only pass doclists with hits (skip if all hits deleted). */
1557 @@ -6628,16 +6896,19 @@ static void createDoclistResult(sqlite3_context *pContext,
1558 const char *pData, int nData){
1559 DataBuffer dump;
1560 DLReader dlReader;
1561 + int rc;
1563 assert( pData!=NULL && nData>0 );
1565 + rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1566 + if( rc!=SQLITE_OK ) return;
1567 dataBufferInit(&dump, 0);
1568 - dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1569 - for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
1570 + for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){
1571 char buf[256];
1572 PLReader plReader;
1574 - plrInit(&plReader, &dlReader);
1575 + rc = plrInit(&plReader, &dlReader);
1576 + if( rc!=SQLITE_OK ) break;
1577 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
1578 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
1579 dataBufferAppend(&dump, buf, strlen(buf));
1580 @@ -6648,7 +6919,8 @@ static void createDoclistResult(sqlite3_context *pContext,
1581 dlrDocid(&dlReader), iColumn);
1582 dataBufferAppend(&dump, buf, strlen(buf));
1584 - for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){
1585 + for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){
1586 + if( rc!=SQLITE_OK ) break;
1587 if( plrColumn(&plReader)!=iColumn ){
1588 iColumn = plrColumn(&plReader);
1589 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
1590 @@ -6669,6 +6941,7 @@ static void createDoclistResult(sqlite3_context *pContext,
1591 dataBufferAppend(&dump, buf, strlen(buf));
1593 plrDestroy(&plReader);
1594 + if( rc!= SQLITE_OK ) break;
1596 assert( dump.nData>0 );
1597 dump.nData--; /* Overwrite trailing space. */
1598 @@ -6677,6 +6950,10 @@ static void createDoclistResult(sqlite3_context *pContext,
1601 dlrDestroy(&dlReader);
1602 + if( rc!=SQLITE_OK ){
1603 + dataBufferDestroy(&dump);
1604 + return;
1607 assert( dump.nData>0 );
1608 dump.nData--; /* Overwrite trailing space. */
1610 2.2.1