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

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

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

Powered by Google App Engine
This is Rietveld 408576698