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

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

Issue 5626002: Update sqlite to 3.7.3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/third_party/sqlite/src
Patch Set: Remove misc change. Created 10 years 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/fts3.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 diff -ru ext-orig/fts2/fts2.c ext/fts2/fts2.c 1 diff --git a/third_party/sqlite/src/ext/fts2/fts2.c b/third_party/sqlite/src/ext /fts2/fts2.c
2 --- ext-orig/fts2/fts2.c» 2009-09-04 13:37:41.000000000 -0700 2 index 74c2890..5ec1265 100644
3 +++ ext/fts2/fts2.c» 2009-09-30 14:48:14.000000000 -0700 3 --- a/third_party/sqlite/src/ext/fts2/fts2.c
4 +++ b/third_party/sqlite/src/ext/fts2/fts2.c
4 @@ -37,6 +37,20 @@ 5 @@ -37,6 +37,20 @@
5 ** This is an SQLite module implementing full-text search. 6 ** This is an SQLite module implementing full-text search.
6 */ 7 */
7 8
8 +/* TODO(shess): To make it easier to spot changes without groveling 9 +/* TODO(shess): To make it easier to spot changes without groveling
9 +** through changelogs, I've defined GEARS_FTS2_CHANGES to call them 10 +** through changelogs, I've defined GEARS_FTS2_CHANGES to call them
10 +** out, and I will document them here. On imports, these changes 11 +** out, and I will document them here. On imports, these changes
11 +** should be reviewed to make sure they are still present, or are 12 +** should be reviewed to make sure they are still present, or are
12 +** dropped as appropriate. 13 +** dropped as appropriate.
13 +** 14 +**
14 +** SQLite core adds the custom function fts2_tokenizer() to be used 15 +** SQLite core adds the custom function fts2_tokenizer() to be used
15 +** for defining new tokenizers. The second parameter is a vtable 16 +** for defining new tokenizers. The second parameter is a vtable
16 +** pointer encoded as a blob. Obviously this cannot be exposed to 17 +** pointer encoded as a blob. Obviously this cannot be exposed to
17 +** Gears callers for security reasons. It could be suppressed in the 18 +** Gears callers for security reasons. It could be suppressed in the
18 +** authorizer, but for now I have simply commented the definition out. 19 +** authorizer, but for now I have simply commented the definition out.
19 +*/ 20 +*/
20 +#define GEARS_FTS2_CHANGES 1 21 +#define GEARS_FTS2_CHANGES 1
21 + 22 +
22 /* 23 /*
23 ** The code in this file is only compiled if: 24 ** The code in this file is only compiled if:
24 ** 25 **
25 @@ -335,6 +349,16 @@ 26 @@ -333,6 +347,16 @@ SQLITE_EXTENSION_INIT1
26 # define TRACE(A) 27 # define TRACE(A)
27 #endif 28 #endif
28 29
29 +#if 0 30 +#if 0
30 +/* Useful to set breakpoints. See main.c sqlite3Corrupt(). */ 31 +/* Useful to set breakpoints. See main.c sqlite3Corrupt(). */
31 +static int fts2Corrupt(void){ 32 +static int fts2Corrupt(void){
32 + return SQLITE_CORRUPT; 33 + return SQLITE_CORRUPT;
33 +} 34 +}
34 +# define SQLITE_CORRUPT_BKPT fts2Corrupt() 35 +# define SQLITE_CORRUPT_BKPT fts2Corrupt()
35 +#else 36 +#else
36 +# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT 37 +# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
37 +#endif 38 +#endif
38 + 39 +
39 /* It is not safe to call isspace(), tolower(), or isalnum() on 40 /* It is not safe to call isspace(), tolower(), or isalnum() on
40 ** hi-bit-set characters. This is the same solution used in the 41 ** hi-bit-set characters. This is the same solution used in the
41 ** tokenizer. 42 ** tokenizer.
42 @@ -423,30 +447,41 @@ 43 @@ -421,30 +445,41 @@ static int putVarint(char *p, sqlite_int64 v){
43 /* Read a 64-bit variable-length integer from memory starting at p[0]. 44 /* Read a 64-bit variable-length integer from memory starting at p[0].
44 * Return the number of bytes read, or 0 on error. 45 * Return the number of bytes read, or 0 on error.
45 * The value is stored in *v. */ 46 * The value is stored in *v. */
46 -static int getVarint(const char *p, sqlite_int64 *v){ 47 -static int getVarint(const char *p, sqlite_int64 *v){
47 +static int getVarintSafe(const char *p, sqlite_int64 *v, int max){ 48 +static int getVarintSafe(const char *p, sqlite_int64 *v, int max){
48 const unsigned char *q = (const unsigned char *) p; 49 const unsigned char *q = (const unsigned char *) p;
49 sqlite_uint64 x = 0, y = 1; 50 sqlite_uint64 x = 0, y = 1;
50 - while( (*q & 0x80) == 0x80 ){ 51 - while( (*q & 0x80) == 0x80 ){
51 + if( max>VARINT_MAX ) max = VARINT_MAX; 52 + if( max>VARINT_MAX ) max = VARINT_MAX;
52 + while( max && (*q & 0x80) == 0x80 ){ 53 + while( max && (*q & 0x80) == 0x80 ){
(...skipping 29 matching lines...) Expand all
82 return ret; 83 return ret;
83 } 84 }
84 85
85 +static int getVarint32(const char* p, int *pi){ 86 +static int getVarint32(const char* p, int *pi){
86 + return getVarint32Safe(p, pi, VARINT_MAX); 87 + return getVarint32Safe(p, pi, VARINT_MAX);
87 +} 88 +}
88 + 89 +
89 /*******************************************************************/ 90 /*******************************************************************/
90 /* DataBuffer is used to collect data into a buffer in piecemeal 91 /* DataBuffer is used to collect data into a buffer in piecemeal
91 ** fashion. It implements the usual distinction between amount of 92 ** fashion. It implements the usual distinction between amount of
92 @@ -615,7 +650,7 @@ 93 @@ -613,7 +648,7 @@ typedef struct DLReader {
93 94
94 static int dlrAtEnd(DLReader *pReader){ 95 static int dlrAtEnd(DLReader *pReader){
95 assert( pReader->nData>=0 ); 96 assert( pReader->nData>=0 );
96 - return pReader->nData==0; 97 - return pReader->nData==0;
97 + return pReader->nData<=0; 98 + return pReader->nData<=0;
98 } 99 }
99 static sqlite_int64 dlrDocid(DLReader *pReader){ 100 static sqlite_int64 dlrDocid(DLReader *pReader){
100 assert( !dlrAtEnd(pReader) ); 101 assert( !dlrAtEnd(pReader) );
101 @@ -639,7 +674,8 @@ 102 @@ -637,7 +672,8 @@ static int dlrAllDataBytes(DLReader *pReader){
102 */ 103 */
103 static const char *dlrPosData(DLReader *pReader){ 104 static const char *dlrPosData(DLReader *pReader){
104 sqlite_int64 iDummy; 105 sqlite_int64 iDummy;
105 - int n = getVarint(pReader->pData, &iDummy); 106 - int n = getVarint(pReader->pData, &iDummy);
106 + int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement); 107 + int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement);
107 + if( !n ) return NULL; 108 + if( !n ) return NULL;
108 assert( !dlrAtEnd(pReader) ); 109 assert( !dlrAtEnd(pReader) );
109 return pReader->pData+n; 110 return pReader->pData+n;
110 } 111 }
111 @@ -649,7 +685,7 @@ 112 @@ -647,7 +683,7 @@ static int dlrPosDataLen(DLReader *pReader){
112 assert( !dlrAtEnd(pReader) ); 113 assert( !dlrAtEnd(pReader) );
113 return pReader->nElement-n; 114 return pReader->nElement-n;
114 } 115 }
115 -static void dlrStep(DLReader *pReader){ 116 -static void dlrStep(DLReader *pReader){
116 +static int dlrStep(DLReader *pReader){ 117 +static int dlrStep(DLReader *pReader){
117 assert( !dlrAtEnd(pReader) ); 118 assert( !dlrAtEnd(pReader) );
118 119
119 /* Skip past current doclist element. */ 120 /* Skip past current doclist element. */
120 @@ -658,32 +694,48 @@ 121 @@ -656,32 +692,48 @@ static void dlrStep(DLReader *pReader){
121 pReader->nData -= pReader->nElement; 122 pReader->nData -= pReader->nElement;
122 123
123 /* If there is more data, read the next doclist element. */ 124 /* If there is more data, read the next doclist element. */
124 - if( pReader->nData!=0 ){ 125 - if( pReader->nData!=0 ){
125 + if( pReader->nData>0 ){ 126 + if( pReader->nData>0 ){
126 sqlite_int64 iDocidDelta; 127 sqlite_int64 iDocidDelta;
127 - int iDummy, n = getVarint(pReader->pData, &iDocidDelta); 128 - int iDummy, n = getVarint(pReader->pData, &iDocidDelta);
128 + int nTotal = 0; 129 + int nTotal = 0;
129 + int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData) ; 130 + int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData) ;
130 + if( !n ) return SQLITE_CORRUPT_BKPT; 131 + if( !n ) return SQLITE_CORRUPT_BKPT;
(...skipping 29 matching lines...) Expand all
160 + if( !n ) return SQLITE_CORRUPT_BKPT; 161 + if( !n ) return SQLITE_CORRUPT_BKPT;
161 + nTotal += n; 162 + nTotal += n;
162 } 163 }
163 } 164 }
164 } 165 }
165 - pReader->nElement = n; 166 - pReader->nElement = n;
166 + pReader->nElement = nTotal; 167 + pReader->nElement = nTotal;
167 assert( pReader->nElement<=pReader->nData ); 168 assert( pReader->nElement<=pReader->nData );
168 } 169 }
169 + return SQLITE_OK; 170 + return SQLITE_OK;
171 +}
172 +static void dlrDestroy(DLReader *pReader){
173 + SCRAMBLE(pReader);
170 } 174 }
171 -static void dlrInit(DLReader *pReader, DocListType iType, 175 -static void dlrInit(DLReader *pReader, DocListType iType,
172 - const char *pData, int nData){ 176 - const char *pData, int nData){
173 +static void dlrDestroy(DLReader *pReader){
174 + SCRAMBLE(pReader);
175 +}
176 +static int dlrInit(DLReader *pReader, DocListType iType, 177 +static int dlrInit(DLReader *pReader, DocListType iType,
177 + const char *pData, int nData){ 178 + const char *pData, int nData){
178 + int rc; 179 + int rc;
179 assert( pData!=NULL && nData!=0 ); 180 assert( pData!=NULL && nData!=0 );
180 pReader->iType = iType; 181 pReader->iType = iType;
181 pReader->pData = pData; 182 pReader->pData = pData;
182 @@ -692,10 +744,9 @@ 183 @@ -690,10 +742,9 @@ static void dlrInit(DLReader *pReader, DocListType iType,
183 pReader->iDocid = 0; 184 pReader->iDocid = 0;
184 185
185 /* Load the first element's data. There must be a first element. */ 186 /* Load the first element's data. There must be a first element. */
186 - dlrStep(pReader); 187 - dlrStep(pReader);
187 -} 188 -}
188 -static void dlrDestroy(DLReader *pReader){ 189 -static void dlrDestroy(DLReader *pReader){
189 - SCRAMBLE(pReader); 190 - SCRAMBLE(pReader);
190 + rc = dlrStep(pReader); 191 + rc = dlrStep(pReader);
191 + if( rc!=SQLITE_OK ) dlrDestroy(pReader); 192 + if( rc!=SQLITE_OK ) dlrDestroy(pReader);
192 + return rc; 193 + return rc;
193 } 194 }
194 195
195 #ifndef NDEBUG 196 #ifndef NDEBUG
196 @@ -782,9 +833,9 @@ 197 @@ -780,9 +831,9 @@ static void dlwDestroy(DLWriter *pWriter){
197 /* TODO(shess) This has become just a helper for docListMerge. 198 /* TODO(shess) This has become just a helper for docListMerge.
198 ** Consider a refactor to make this cleaner. 199 ** Consider a refactor to make this cleaner.
199 */ 200 */
200 -static void dlwAppend(DLWriter *pWriter, 201 -static void dlwAppend(DLWriter *pWriter,
201 - const char *pData, int nData, 202 - const char *pData, int nData,
202 - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ 203 - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
203 +static int dlwAppend(DLWriter *pWriter, 204 +static int dlwAppend(DLWriter *pWriter,
204 + const char *pData, int nData, 205 + const char *pData, int nData,
205 + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ 206 + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
206 sqlite_int64 iDocid = 0; 207 sqlite_int64 iDocid = 0;
207 char c[VARINT_MAX]; 208 char c[VARINT_MAX];
208 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ 209 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */
209 @@ -793,7 +844,8 @@ 210 @@ -791,7 +842,8 @@ static void dlwAppend(DLWriter *pWriter,
210 #endif 211 #endif
211 212
212 /* Recode the initial docid as delta from iPrevDocid. */ 213 /* Recode the initial docid as delta from iPrevDocid. */
213 - nFirstOld = getVarint(pData, &iDocid); 214 - nFirstOld = getVarint(pData, &iDocid);
214 + nFirstOld = getVarintSafe(pData, &iDocid, nData); 215 + nFirstOld = getVarintSafe(pData, &iDocid, nData);
215 + if( !nFirstOld ) return SQLITE_CORRUPT_BKPT; 216 + if( !nFirstOld ) return SQLITE_CORRUPT_BKPT;
216 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) ); 217 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
217 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid); 218 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);
218 219
219 @@ -814,10 +866,11 @@ 220 @@ -812,10 +864,11 @@ static void dlwAppend(DLWriter *pWriter,
220 dataBufferAppend(pWriter->b, c, nFirstNew); 221 dataBufferAppend(pWriter->b, c, nFirstNew);
221 } 222 }
222 pWriter->iPrevDocid = iLastDocid; 223 pWriter->iPrevDocid = iLastDocid;
223 + return SQLITE_OK; 224 + return SQLITE_OK;
224 } 225 }
225 -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ 226 -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){
226 - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), 227 - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
227 - dlrDocid(pReader), dlrDocid(pReader)); 228 - dlrDocid(pReader), dlrDocid(pReader));
228 +static int dlwCopy(DLWriter *pWriter, DLReader *pReader){ 229 +static int dlwCopy(DLWriter *pWriter, DLReader *pReader){
229 + return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), 230 + return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
230 + dlrDocid(pReader), dlrDocid(pReader)); 231 + dlrDocid(pReader), dlrDocid(pReader));
231 } 232 }
232 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ 233 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
233 char c[VARINT_MAX]; 234 char c[VARINT_MAX];
234 @@ -878,45 +931,63 @@ 235 @@ -876,45 +929,63 @@ static int plrEndOffset(PLReader *pReader){
235 assert( !plrAtEnd(pReader) ); 236 assert( !plrAtEnd(pReader) );
236 return pReader->iEndOffset; 237 return pReader->iEndOffset;
237 } 238 }
238 -static void plrStep(PLReader *pReader){ 239 -static void plrStep(PLReader *pReader){
239 - int i, n; 240 - int i, n;
240 +static int plrStep(PLReader *pReader){ 241 +static int plrStep(PLReader *pReader){
241 + int i, n, nTotal = 0; 242 + int i, n, nTotal = 0;
242 243
243 assert( !plrAtEnd(pReader) ); 244 assert( !plrAtEnd(pReader) );
244 245
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 -static void plrInit(PLReader *pReader, DLReader *pDLReader){ 303 -static void plrInit(PLReader *pReader, DLReader *pDLReader){
303 +static void plrDestroy(PLReader *pReader){ 304 +static void plrDestroy(PLReader *pReader){
304 + SCRAMBLE(pReader); 305 + SCRAMBLE(pReader);
305 +} 306 +}
306 + 307 +
307 +static int plrInit(PLReader *pReader, DLReader *pDLReader){ 308 +static int plrInit(PLReader *pReader, DLReader *pDLReader){
308 + int rc; 309 + int rc;
309 pReader->pData = dlrPosData(pDLReader); 310 pReader->pData = dlrPosData(pDLReader);
310 pReader->nData = dlrPosDataLen(pDLReader); 311 pReader->nData = dlrPosDataLen(pDLReader);
311 pReader->iType = pDLReader->iType; 312 pReader->iType = pDLReader->iType;
312 @@ -924,10 +995,9 @@ 313 @@ -922,10 +993,9 @@ static void plrInit(PLReader *pReader, DLReader *pDLReader) {
313 pReader->iPosition = 0; 314 pReader->iPosition = 0;
314 pReader->iStartOffset = 0; 315 pReader->iStartOffset = 0;
315 pReader->iEndOffset = 0; 316 pReader->iEndOffset = 0;
316 - plrStep(pReader); 317 - plrStep(pReader);
317 -} 318 -}
318 -static void plrDestroy(PLReader *pReader){ 319 -static void plrDestroy(PLReader *pReader){
319 - SCRAMBLE(pReader); 320 - SCRAMBLE(pReader);
320 + rc = plrStep(pReader); 321 + rc = plrStep(pReader);
321 + if( rc!=SQLITE_OK ) plrDestroy(pReader); 322 + if( rc!=SQLITE_OK ) plrDestroy(pReader);
322 + return rc; 323 + return rc;
323 } 324 }
324 325
325 /*******************************************************************/ 326 /*******************************************************************/
326 @@ -1113,14 +1183,16 @@ 327 @@ -1111,14 +1181,16 @@ static void dlcDelete(DLCollector *pCollector){
327 ** deletion will be trimmed, and will thus not effect a deletion 328 ** deletion will be trimmed, and will thus not effect a deletion
328 ** during the merge. 329 ** during the merge.
329 */ 330 */
330 -static void docListTrim(DocListType iType, const char *pData, int nData, 331 -static void docListTrim(DocListType iType, const char *pData, int nData,
331 - int iColumn, DocListType iOutType, DataBuffer *out){ 332 - int iColumn, DocListType iOutType, DataBuffer *out){
332 +static int docListTrim(DocListType iType, const char *pData, int nData, 333 +static int docListTrim(DocListType iType, const char *pData, int nData,
333 + int iColumn, DocListType iOutType, DataBuffer *out){ 334 + int iColumn, DocListType iOutType, DataBuffer *out){
334 DLReader dlReader; 335 DLReader dlReader;
335 DLWriter dlWriter; 336 DLWriter dlWriter;
336 + int rc; 337 + int rc;
337 338
338 assert( iOutType<=iType ); 339 assert( iOutType<=iType );
339 340
340 - dlrInit(&dlReader, iType, pData, nData); 341 - dlrInit(&dlReader, iType, pData, nData);
341 + rc = dlrInit(&dlReader, iType, pData, nData); 342 + rc = dlrInit(&dlReader, iType, pData, nData);
342 + if( rc!=SQLITE_OK ) return rc; 343 + if( rc!=SQLITE_OK ) return rc;
343 dlwInit(&dlWriter, iOutType, out); 344 dlwInit(&dlWriter, iOutType, out);
344 345
345 while( !dlrAtEnd(&dlReader) ){ 346 while( !dlrAtEnd(&dlReader) ){
346 @@ -1128,7 +1200,8 @@ 347 @@ -1126,7 +1198,8 @@ static void docListTrim(DocListType iType, const char *pDa ta, int nData,
347 PLWriter plWriter; 348 PLWriter plWriter;
348 int match = 0; 349 int match = 0;
349 350
350 - plrInit(&plReader, &dlReader); 351 - plrInit(&plReader, &dlReader);
351 + rc = plrInit(&plReader, &dlReader); 352 + rc = plrInit(&plReader, &dlReader);
352 + if( rc!=SQLITE_OK ) break; 353 + if( rc!=SQLITE_OK ) break;
353 354
354 while( !plrAtEnd(&plReader) ){ 355 while( !plrAtEnd(&plReader) ){
355 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ 356 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
356 @@ -1139,7 +1212,11 @@ 357 @@ -1137,7 +1210,11 @@ static void docListTrim(DocListType iType, const char *pD ata, int nData,
357 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), 358 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
358 plrStartOffset(&plReader), plrEndOffset(&plReader)); 359 plrStartOffset(&plReader), plrEndOffset(&plReader));
359 } 360 }
360 - plrStep(&plReader); 361 - plrStep(&plReader);
361 + rc = plrStep(&plReader); 362 + rc = plrStep(&plReader);
362 + if( rc!=SQLITE_OK ){ 363 + if( rc!=SQLITE_OK ){
363 + plrDestroy(&plReader); 364 + plrDestroy(&plReader);
364 + goto err; 365 + goto err;
365 + } 366 + }
366 } 367 }
367 if( match ){ 368 if( match ){
368 plwTerminate(&plWriter); 369 plwTerminate(&plWriter);
369 @@ -1147,10 +1224,13 @@ 370 @@ -1145,10 +1222,13 @@ static void docListTrim(DocListType iType, const char *p Data, int nData,
370 } 371 }
371 372
372 plrDestroy(&plReader); 373 plrDestroy(&plReader);
373 - dlrStep(&dlReader); 374 - dlrStep(&dlReader);
374 + rc = dlrStep(&dlReader); 375 + rc = dlrStep(&dlReader);
375 + if( rc!=SQLITE_OK ) break; 376 + if( rc!=SQLITE_OK ) break;
376 } 377 }
377 +err: 378 +err:
378 dlwDestroy(&dlWriter); 379 dlwDestroy(&dlWriter);
379 dlrDestroy(&dlReader); 380 dlrDestroy(&dlReader);
380 + return rc; 381 + return rc;
381 } 382 }
382 383
383 /* Used by docListMerge() to keep doclists in the ascending order by 384 /* Used by docListMerge() to keep doclists in the ascending order by
384 @@ -1207,19 +1287,20 @@ 385 @@ -1205,19 +1285,20 @@ static void orderedDLReaderReorder(OrderedDLReader *p, i nt n){
385 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably 386 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably
386 ** be fixed. 387 ** be fixed.
387 */ 388 */
388 -static void docListMerge(DataBuffer *out, 389 -static void docListMerge(DataBuffer *out,
389 - DLReader *pReaders, int nReaders){ 390 - DLReader *pReaders, int nReaders){
390 +static int docListMerge(DataBuffer *out, 391 +static int docListMerge(DataBuffer *out,
391 + DLReader *pReaders, int nReaders){ 392 + DLReader *pReaders, int nReaders){
392 OrderedDLReader readers[MERGE_COUNT]; 393 OrderedDLReader readers[MERGE_COUNT];
393 DLWriter writer; 394 DLWriter writer;
394 int i, n; 395 int i, n;
395 const char *pStart = 0; 396 const char *pStart = 0;
396 int nStart = 0; 397 int nStart = 0;
397 sqlite_int64 iFirstDocid = 0, iLastDocid = 0; 398 sqlite_int64 iFirstDocid = 0, iLastDocid = 0;
398 + int rc = SQLITE_OK; 399 + int rc = SQLITE_OK;
399 400
400 assert( nReaders>0 ); 401 assert( nReaders>0 );
401 if( nReaders==1 ){ 402 if( nReaders==1 ){
402 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); 403 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
403 - return; 404 - return;
404 + return SQLITE_OK; 405 + return SQLITE_OK;
405 } 406 }
406 407
407 assert( nReaders<=MERGE_COUNT ); 408 assert( nReaders<=MERGE_COUNT );
408 @@ -1252,20 +1333,23 @@ 409 @@ -1250,20 +1331,23 @@ static void docListMerge(DataBuffer *out,
409 nStart += dlrDocDataBytes(readers[0].pReader); 410 nStart += dlrDocDataBytes(readers[0].pReader);
410 }else{ 411 }else{
411 if( pStart!=0 ){ 412 if( pStart!=0 ){
412 - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 413 - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
413 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 414 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
414 + if( rc!=SQLITE_OK ) goto err; 415 + if( rc!=SQLITE_OK ) goto err;
415 } 416 }
416 pStart = dlrDocData(readers[0].pReader); 417 pStart = dlrDocData(readers[0].pReader);
417 nStart = dlrDocDataBytes(readers[0].pReader); 418 nStart = dlrDocDataBytes(readers[0].pReader);
418 iFirstDocid = iDocid; 419 iFirstDocid = iDocid;
419 } 420 }
420 iLastDocid = iDocid; 421 iLastDocid = iDocid;
421 - dlrStep(readers[0].pReader); 422 - dlrStep(readers[0].pReader);
422 + rc = dlrStep(readers[0].pReader); 423 + rc = dlrStep(readers[0].pReader);
423 + if( rc!=SQLITE_OK ) goto err; 424 + if( rc!=SQLITE_OK ) goto err;
424 425
425 /* Drop all of the older elements with the same docid. */ 426 /* Drop all of the older elements with the same docid. */
426 for(i=1; i<nReaders && 427 for(i=1; i<nReaders &&
427 !dlrAtEnd(readers[i].pReader) && 428 !dlrAtEnd(readers[i].pReader) &&
428 dlrDocid(readers[i].pReader)==iDocid; i++){ 429 dlrDocid(readers[i].pReader)==iDocid; i++){
429 - dlrStep(readers[i].pReader); 430 - dlrStep(readers[i].pReader);
430 + rc = dlrStep(readers[i].pReader); 431 + rc = dlrStep(readers[i].pReader);
431 + if( rc!=SQLITE_OK ) goto err; 432 + if( rc!=SQLITE_OK ) goto err;
432 } 433 }
433 434
434 /* Get the readers back into order. */ 435 /* Get the readers back into order. */
435 @@ -1275,8 +1359,11 @@ 436 @@ -1273,8 +1357,11 @@ static void docListMerge(DataBuffer *out,
436 } 437 }
437 438
438 /* Copy over any remaining elements. */ 439 /* Copy over any remaining elements. */
439 - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 440 - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
440 + if( nStart>0 ) 441 + if( nStart>0 )
441 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 442 + rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
442 +err: 443 +err:
443 dlwDestroy(&writer); 444 dlwDestroy(&writer);
444 + return rc; 445 + return rc;
445 } 446 }
446 447
447 /* Helper function for posListUnion(). Compares the current position 448 /* Helper function for posListUnion(). Compares the current position
448 @@ -1312,30 +1399,40 @@ 449 @@ -1310,30 +1397,40 @@ static int posListCmp(PLReader *pLeft, PLReader *pRight) {
449 ** work with any doclist type, though both inputs and the output 450 ** work with any doclist type, though both inputs and the output
450 ** should be the same type. 451 ** should be the same type.
451 */ 452 */
452 -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ 453 -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
453 +static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ 454 +static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
454 PLReader left, right; 455 PLReader left, right;
455 PLWriter writer; 456 PLWriter writer;
456 + int rc; 457 + int rc;
457 458
458 assert( dlrDocid(pLeft)==dlrDocid(pRight) ); 459 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
(...skipping 27 matching lines...) Expand all
486 plwCopy(&writer, &left); 487 plwCopy(&writer, &left);
487 - plrStep(&left); 488 - plrStep(&left);
488 - plrStep(&right); 489 - plrStep(&right);
489 + rc = plrStep(&left); 490 + rc = plrStep(&left);
490 + if( rc != SQLITE_OK ) break; 491 + if( rc != SQLITE_OK ) break;
491 + rc = plrStep(&right); 492 + rc = plrStep(&right);
492 + if( rc != SQLITE_OK ) break; 493 + if( rc != SQLITE_OK ) break;
493 } 494 }
494 } 495 }
495 496
496 @@ -1343,56 +1440,75 @@ 497 @@ -1341,56 +1438,75 @@ static void posListUnion(DLReader *pLeft, DLReader *pRig ht, DLWriter *pOut){
497 plwDestroy(&writer); 498 plwDestroy(&writer);
498 plrDestroy(&left); 499 plrDestroy(&left);
499 plrDestroy(&right); 500 plrDestroy(&right);
500 + return rc; 501 + return rc;
501 } 502 }
502 503
503 /* Write the union of doclists in pLeft and pRight to pOut. For 504 /* Write the union of doclists in pLeft and pRight to pOut. For
504 ** docids in common between the inputs, the union of the position 505 ** docids in common between the inputs, the union of the position
505 ** lists is written. Inputs and outputs are always type DL_DEFAULT. 506 ** lists is written. Inputs and outputs are always type DL_DEFAULT.
506 */ 507 */
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 } 579 }
579 } 580 }
580 581
581 dlrDestroy(&left); 582 dlrDestroy(&left);
582 dlrDestroy(&right); 583 dlrDestroy(&right);
583 dlwDestroy(&writer); 584 dlwDestroy(&writer);
584 + return rc; 585 + return rc;
585 } 586 }
586 587
587 /* pLeft and pRight are DLReaders positioned to the same docid. 588 /* pLeft and pRight are DLReaders positioned to the same docid.
588 @@ -1407,35 +1523,47 @@ 589 @@ -1405,35 +1521,47 @@ static void docListUnion(
589 ** include the positions from pRight that are one more than a 590 ** include the positions from pRight that are one more than a
590 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1. 591 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
591 */ 592 */
592 -static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight, 593 -static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
593 - DLWriter *pOut){ 594 - DLWriter *pOut){
594 +static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight, 595 +static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
595 + DLWriter *pOut){ 596 + DLWriter *pOut){
596 PLReader left, right; 597 PLReader left, right;
597 PLWriter writer; 598 PLWriter writer;
598 int match = 0; 599 int match = 0;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); 637 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
637 - plrStep(&left); 638 - plrStep(&left);
638 - plrStep(&right); 639 - plrStep(&right);
639 + rc = plrStep(&left); 640 + rc = plrStep(&left);
640 + if( rc!=SQLITE_OK ) break; 641 + if( rc!=SQLITE_OK ) break;
641 + rc = plrStep(&right); 642 + rc = plrStep(&right);
642 + if( rc!=SQLITE_OK ) break; 643 + if( rc!=SQLITE_OK ) break;
643 } 644 }
644 } 645 }
645 646
646 @@ -1446,6 +1574,7 @@ 647 @@ -1444,6 +1572,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader * pRight,
647 648
648 plrDestroy(&left); 649 plrDestroy(&left);
649 plrDestroy(&right); 650 plrDestroy(&right);
650 + return rc; 651 + return rc;
651 } 652 }
652 653
653 /* We have two doclists with positions: pLeft and pRight. 654 /* We have two doclists with positions: pLeft and pRight.
654 @@ -1457,7 +1586,7 @@ 655 @@ -1455,7 +1584,7 @@ static void posListPhraseMerge(DLReader *pLeft, DLReader * pRight,
655 ** iType controls the type of data written to pOut. If iType is 656 ** iType controls the type of data written to pOut. If iType is
656 ** DL_POSITIONS, the positions are those from pRight. 657 ** DL_POSITIONS, the positions are those from pRight.
657 */ 658 */
658 -static void docListPhraseMerge( 659 -static void docListPhraseMerge(
659 +static int docListPhraseMerge( 660 +static int docListPhraseMerge(
660 const char *pLeft, int nLeft, 661 const char *pLeft, int nLeft,
661 const char *pRight, int nRight, 662 const char *pRight, int nRight,
662 DocListType iType, 663 DocListType iType,
663 @@ -1465,152 +1594,198 @@ 664 @@ -1463,152 +1592,198 @@ static void docListPhraseMerge(
664 ){ 665 ){
665 DLReader left, right; 666 DLReader left, right;
666 DLWriter writer; 667 DLWriter writer;
667 + int rc; 668 + int rc;
668 669
669 - if( nLeft==0 || nRight==0 ) return; 670 - if( nLeft==0 || nRight==0 ) return;
670 + if( nLeft==0 || nRight==0 ) return SQLITE_OK; 671 + if( nLeft==0 || nRight==0 ) return SQLITE_OK;
671 672
672 assert( iType!=DL_POSITIONS_OFFSETS ); 673 assert( iType!=DL_POSITIONS_OFFSETS );
673 674
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 } 887 }
887 888
888 +err: 889 +err:
889 dlrDestroy(&left); 890 dlrDestroy(&left);
890 dlrDestroy(&right); 891 dlrDestroy(&right);
891 dlwDestroy(&writer); 892 dlwDestroy(&writer);
892 + return rc; 893 + return rc;
893 } 894 }
894 895
895 static char *string_dup_n(const char *s, int n){ 896 static char *string_dup_n(const char *s, int n){
896 @@ -1814,7 +1989,7 @@ 897 @@ -1812,7 +1987,7 @@ static const char *const fulltext_zStatement[MAX_STMT] = {
897 /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?", 898 /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?",
898 /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)", 899 /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)",
899 /* SEGDIR_SELECT_LEVEL */ 900 /* SEGDIR_SELECT_LEVEL */
900 - "select start_block, leaves_end_block, root from %_segdir " 901 - "select start_block, leaves_end_block, root from %_segdir "
901 + "select start_block, leaves_end_block, root, idx from %_segdir " 902 + "select start_block, leaves_end_block, root, idx from %_segdir "
902 " where level = ? order by idx", 903 " where level = ? order by idx",
903 /* SEGDIR_SPAN */ 904 /* SEGDIR_SPAN */
904 "select min(start_block), max(end_block) from %_segdir " 905 "select min(start_block), max(end_block) from %_segdir "
905 @@ -3413,7 +3588,8 @@ 906 @@ -3411,7 +3586,8 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){
906 return SQLITE_OK; 907 return SQLITE_OK;
907 } 908 }
908 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); 909 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
909 - dlrStep(&c->reader); 910 - dlrStep(&c->reader);
910 + if( rc!=SQLITE_OK ) return rc; 911 + if( rc!=SQLITE_OK ) return rc;
911 + rc = dlrStep(&c->reader); 912 + rc = dlrStep(&c->reader);
912 if( rc!=SQLITE_OK ) return rc; 913 if( rc!=SQLITE_OK ) return rc;
913 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ 914 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
914 rc = sqlite3_step(c->pStmt); 915 rc = sqlite3_step(c->pStmt);
915 @@ -3421,8 +3597,11 @@ 916 @@ -3419,8 +3595,11 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){
916 c->eof = 0; 917 c->eof = 0;
917 return SQLITE_OK; 918 return SQLITE_OK;
918 } 919 }
919 - /* an error occurred; abort */ 920 - /* an error occurred; abort */
920 - return rc==SQLITE_DONE ? SQLITE_ERROR : rc; 921 - return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
921 + 922 +
922 + /* Corrupt if the index refers to missing document. */ 923 + /* Corrupt if the index refers to missing document. */
923 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT; 924 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
924 + 925 +
925 + return rc; 926 + return rc;
926 } 927 }
927 } 928 }
928 929
929 @@ -3470,14 +3649,18 @@ 930 @@ -3468,14 +3647,18 @@ static int docListOfTerm(
930 return rc; 931 return rc;
931 } 932 }
932 dataBufferInit(&new, 0); 933 dataBufferInit(&new, 0);
933 - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, 934 - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
934 - i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new); 935 - i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
935 + rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, 936 + rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
936 + i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new) ; 937 + i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new) ;
937 dataBufferDestroy(&left); 938 dataBufferDestroy(&left);
938 dataBufferDestroy(&right); 939 dataBufferDestroy(&right);
939 + if( rc!=SQLITE_OK ){ 940 + if( rc!=SQLITE_OK ){
940 + dataBufferDestroy(&new); 941 + dataBufferDestroy(&new);
941 + return rc; 942 + return rc;
942 + } 943 + }
943 left = new; 944 left = new;
944 } 945 }
945 *pResult = left; 946 *pResult = left;
946 - return SQLITE_OK; 947 - return SQLITE_OK;
947 + return rc; 948 + return rc;
948 } 949 }
949 950
950 /* Add a new term pTerm[0..nTerm-1] to the query *q. 951 /* Add a new term pTerm[0..nTerm-1] to the query *q.
951 @@ -3544,6 +3727,7 @@ 952 @@ -3542,6 +3725,7 @@ static int tokenizeSegment(
952 int firstIndex = pQuery->nTerms; 953 int firstIndex = pQuery->nTerms;
953 int iCol; 954 int iCol;
954 int nTerm = 1; 955 int nTerm = 1;
955 + int iEndLast = -1; 956 + int iEndLast = -1;
956 957
957 int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); 958 int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
958 if( rc!=SQLITE_OK ) return rc; 959 if( rc!=SQLITE_OK ) return rc;
959 @@ -3568,6 +3752,20 @@ 960 @@ -3566,6 +3750,20 @@ static int tokenizeSegment(
960 pQuery->nextIsOr = 1; 961 pQuery->nextIsOr = 1;
961 continue; 962 continue;
962 } 963 }
963 + 964 +
964 + /* 965 + /*
965 + * The ICU tokenizer considers '*' a break character, so the code below 966 + * The ICU tokenizer considers '*' a break character, so the code below
966 + * sets isPrefix correctly, but since that code doesn't eat the '*', the 967 + * sets isPrefix correctly, but since that code doesn't eat the '*', the
967 + * ICU tokenizer returns it as the next token. So eat it here until a 968 + * ICU tokenizer returns it as the next token. So eat it here until a
968 + * better solution presents itself. 969 + * better solution presents itself.
969 + */ 970 + */
970 + if( pQuery->nTerms>0 && nToken==1 && pSegment[iBegin]=='*' && 971 + if( pQuery->nTerms>0 && nToken==1 && pSegment[iBegin]=='*' &&
971 + iEndLast==iBegin){ 972 + iEndLast==iBegin){
972 + pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1; 973 + pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
973 + continue; 974 + continue;
974 + } 975 + }
975 + iEndLast = iEnd; 976 + iEndLast = iEnd;
976 + 977 +
977 queryAdd(pQuery, pToken, nToken); 978 queryAdd(pQuery, pToken, nToken);
978 if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ 979 if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
979 pQuery->pTerms[pQuery->nTerms-1].isNot = 1; 980 pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
980 @@ -3707,18 +3905,30 @@ 981 @@ -3705,18 +3903,30 @@ static int fulltextQuery(
981 return rc; 982 return rc;
982 } 983 }
983 dataBufferInit(&new, 0); 984 dataBufferInit(&new, 0);
984 - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); 985 - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
985 + rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); 986 + rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
986 dataBufferDestroy(&right); 987 dataBufferDestroy(&right);
987 dataBufferDestroy(&or); 988 dataBufferDestroy(&or);
988 + if( rc!=SQLITE_OK ){ 989 + if( rc!=SQLITE_OK ){
989 + if( i!=nNot ) dataBufferDestroy(&left); 990 + if( i!=nNot ) dataBufferDestroy(&left);
990 + queryClear(pQuery); 991 + queryClear(pQuery);
(...skipping 12 matching lines...) Expand all
1003 dataBufferDestroy(&right); 1004 dataBufferDestroy(&right);
1004 dataBufferDestroy(&left); 1005 dataBufferDestroy(&left);
1005 + if( rc!=SQLITE_OK ){ 1006 + if( rc!=SQLITE_OK ){
1006 + queryClear(pQuery); 1007 + queryClear(pQuery);
1007 + dataBufferDestroy(&new); 1008 + dataBufferDestroy(&new);
1008 + return rc; 1009 + return rc;
1009 + } 1010 + }
1010 left = new; 1011 left = new;
1011 } 1012 }
1012 } 1013 }
1013 @@ -3738,9 +3948,15 @@ 1014 @@ -3736,9 +3946,15 @@ static int fulltextQuery(
1014 return rc; 1015 return rc;
1015 } 1016 }
1016 dataBufferInit(&new, 0); 1017 dataBufferInit(&new, 0);
1017 - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); 1018 - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new);
1018 + rc = docListExceptMerge(left.pData, left.nData, 1019 + rc = docListExceptMerge(left.pData, left.nData,
1019 + right.pData, right.nData, &new); 1020 + right.pData, right.nData, &new);
1020 dataBufferDestroy(&right); 1021 dataBufferDestroy(&right);
1021 dataBufferDestroy(&left); 1022 dataBufferDestroy(&left);
1022 + if( rc!=SQLITE_OK ){ 1023 + if( rc!=SQLITE_OK ){
1023 + queryClear(pQuery); 1024 + queryClear(pQuery);
1024 + dataBufferDestroy(&new); 1025 + dataBufferDestroy(&new);
1025 + return rc; 1026 + return rc;
1026 + } 1027 + }
1027 left = new; 1028 left = new;
1028 } 1029 }
1029 1030
1030 @@ -3834,7 +4050,8 @@ 1031 @@ -3832,7 +4048,8 @@ static int fulltextFilter(
1031 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c-> q); 1032 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c-> q);
1032 if( rc!=SQLITE_OK ) return rc; 1033 if( rc!=SQLITE_OK ) return rc;
1033 if( c->result.nData!=0 ){ 1034 if( c->result.nData!=0 ){
1034 - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); 1035 - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
1035 + rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); 1036 + rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
1036 + if( rc!=SQLITE_OK ) return rc; 1037 + if( rc!=SQLITE_OK ) return rc;
1037 } 1038 }
1038 break; 1039 break;
1039 } 1040 }
1040 @@ -4335,22 +4552,19 @@ 1041 @@ -4333,22 +4550,19 @@ static void interiorReaderDestroy(InteriorReader *pReade r){
1041 SCRAMBLE(pReader); 1042 SCRAMBLE(pReader);
1042 } 1043 }
1043 1044
1044 -/* TODO(shess) The assertions are great, but what if we're in NDEBUG 1045 -/* TODO(shess) The assertions are great, but what if we're in NDEBUG
1045 -** and the blob is empty or otherwise contains suspect data? 1046 -** and the blob is empty or otherwise contains suspect data?
1046 -*/ 1047 -*/
1047 -static void interiorReaderInit(const char *pData, int nData, 1048 -static void interiorReaderInit(const char *pData, int nData,
1048 - InteriorReader *pReader){ 1049 - InteriorReader *pReader){
1049 +static int interiorReaderInit(const char *pData, int nData, 1050 +static int interiorReaderInit(const char *pData, int nData,
1050 + InteriorReader *pReader){ 1051 + InteriorReader *pReader){
1051 int n, nTerm; 1052 int n, nTerm;
1052 1053
1053 - /* Require at least the leading flag byte */ 1054 - /* Require at least the leading flag byte */
1054 + /* These conditions are checked and met by the callers. */ 1055 + /* These conditions are checked and met by the callers. */
1055 assert( nData>0 ); 1056 assert( nData>0 );
1056 assert( pData[0]!='\0' ); 1057 assert( pData[0]!='\0' );
1057 1058
1058 CLEAR(pReader); 1059 CLEAR(pReader);
1059 1060
1060 /* Decode the base blockid, and set the cursor to the first term. */ 1061 /* Decode the base blockid, and set the cursor to the first term. */
1061 - n = getVarint(pData+1, &pReader->iBlockid); 1062 - n = getVarint(pData+1, &pReader->iBlockid);
1062 - assert( 1+n<=nData ); 1063 - assert( 1+n<=nData );
1063 + n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1); 1064 + n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1);
1064 + if( !n ) return SQLITE_CORRUPT_BKPT; 1065 + if( !n ) return SQLITE_CORRUPT_BKPT;
1065 pReader->pData = pData+1+n; 1066 pReader->pData = pData+1+n;
1066 pReader->nData = nData-(1+n); 1067 pReader->nData = nData-(1+n);
1067 1068
1068 @@ -4361,17 +4575,18 @@ 1069 @@ -4359,17 +4573,18 @@ static void interiorReaderInit(const char *pData, int nD ata,
1069 if( pReader->nData==0 ){ 1070 if( pReader->nData==0 ){
1070 dataBufferInit(&pReader->term, 0); 1071 dataBufferInit(&pReader->term, 0);
1071 }else{ 1072 }else{
1072 - n = getVarint32(pReader->pData, &nTerm); 1073 - n = getVarint32(pReader->pData, &nTerm);
1073 + n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData); 1074 + n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData);
1074 + if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT; 1075 + if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT;
1075 dataBufferInit(&pReader->term, nTerm); 1076 dataBufferInit(&pReader->term, nTerm);
1076 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); 1077 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
1077 - assert( n+nTerm<=pReader->nData ); 1078 - assert( n+nTerm<=pReader->nData );
1078 pReader->pData += n+nTerm; 1079 pReader->pData += n+nTerm;
1079 pReader->nData -= n+nTerm; 1080 pReader->nData -= n+nTerm;
1080 } 1081 }
1081 + return SQLITE_OK; 1082 + return SQLITE_OK;
1082 } 1083 }
1083 1084
1084 static int interiorReaderAtEnd(InteriorReader *pReader){ 1085 static int interiorReaderAtEnd(InteriorReader *pReader){
1085 - return pReader->term.nData==0; 1086 - return pReader->term.nData==0;
1086 + return pReader->term.nData<=0; 1087 + return pReader->term.nData<=0;
1087 } 1088 }
1088 1089
1089 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ 1090 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
1090 @@ -4388,7 +4603,7 @@ 1091 @@ -4386,7 +4601,7 @@ static const char *interiorReaderTerm(InteriorReader *pRea der){
1091 } 1092 }
1092 1093
1093 /* Step forward to the next term in the node. */ 1094 /* Step forward to the next term in the node. */
1094 -static void interiorReaderStep(InteriorReader *pReader){ 1095 -static void interiorReaderStep(InteriorReader *pReader){
1095 +static int interiorReaderStep(InteriorReader *pReader){ 1096 +static int interiorReaderStep(InteriorReader *pReader){
1096 assert( !interiorReaderAtEnd(pReader) ); 1097 assert( !interiorReaderAtEnd(pReader) );
1097 1098
1098 /* If the last term has been read, signal eof, else construct the 1099 /* If the last term has been read, signal eof, else construct the
1099 @@ -4399,18 +4614,26 @@ 1100 @@ -4397,18 +4612,26 @@ static void interiorReaderStep(InteriorReader *pReader){
1100 }else{ 1101 }else{
1101 int n, nPrefix, nSuffix; 1102 int n, nPrefix, nSuffix;
1102 1103
1103 - n = getVarint32(pReader->pData, &nPrefix); 1104 - n = getVarint32(pReader->pData, &nPrefix);
1104 - n += getVarint32(pReader->pData+n, &nSuffix); 1105 - n += getVarint32(pReader->pData+n, &nSuffix);
1105 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData); 1106 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1106 + if( !n ) return SQLITE_CORRUPT_BKPT; 1107 + if( !n ) return SQLITE_CORRUPT_BKPT;
1107 + pReader->nData -= n; 1108 + pReader->nData -= n;
1108 + pReader->pData += n; 1109 + pReader->pData += n;
1109 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData); 1110 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
(...skipping 12 matching lines...) Expand all
1122 - pReader->pData += n+nSuffix; 1123 - pReader->pData += n+nSuffix;
1123 - pReader->nData -= n+nSuffix; 1124 - pReader->nData -= n+nSuffix;
1124 + pReader->pData += nSuffix; 1125 + pReader->pData += nSuffix;
1125 + pReader->nData -= nSuffix; 1126 + pReader->nData -= nSuffix;
1126 } 1127 }
1127 pReader->iBlockid++; 1128 pReader->iBlockid++;
1128 + return SQLITE_OK; 1129 + return SQLITE_OK;
1129 } 1130 }
1130 1131
1131 /* Compare the current term to pTerm[nTerm], returning strcmp-style 1132 /* Compare the current term to pTerm[nTerm], returning strcmp-style
1132 @@ -4782,7 +5005,8 @@ 1133 @@ -4780,7 +5003,8 @@ static int leafWriterStepMerge(fulltext_vtab *v, LeafWrite r *pWriter,
1133 n = putVarint(c, nData); 1134 n = putVarint(c, nData);
1134 dataBufferAppend(&pWriter->data, c, n); 1135 dataBufferAppend(&pWriter->data, c, n);
1135 1136
1136 - docListMerge(&pWriter->data, pReaders, nReaders); 1137 - docListMerge(&pWriter->data, pReaders, nReaders);
1137 + rc = docListMerge(&pWriter->data, pReaders, nReaders); 1138 + rc = docListMerge(&pWriter->data, pReaders, nReaders);
1138 + if( rc!= SQLITE_OK ) return rc; 1139 + if( rc!= SQLITE_OK ) return rc;
1139 ASSERT_VALID_DOCLIST(DL_DEFAULT, 1140 ASSERT_VALID_DOCLIST(DL_DEFAULT,
1140 pWriter->data.pData+iDoclistData+n, 1141 pWriter->data.pData+iDoclistData+n,
1141 pWriter->data.nData-iDoclistData-n, NULL); 1142 pWriter->data.nData-iDoclistData-n, NULL);
1142 @@ -4892,7 +5116,8 @@ 1143 @@ -4890,7 +5114,8 @@ static int leafWriterStep(fulltext_vtab *v, LeafWriter *pW riter,
1143 int rc; 1144 int rc;
1144 DLReader reader; 1145 DLReader reader;
1145 1146
1146 - dlrInit(&reader, DL_DEFAULT, pData, nData); 1147 - dlrInit(&reader, DL_DEFAULT, pData, nData);
1147 + rc = dlrInit(&reader, DL_DEFAULT, pData, nData); 1148 + rc = dlrInit(&reader, DL_DEFAULT, pData, nData);
1148 + if( rc!=SQLITE_OK ) return rc; 1149 + if( rc!=SQLITE_OK ) return rc;
1149 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); 1150 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
1150 dlrDestroy(&reader); 1151 dlrDestroy(&reader);
1151 1152
1152 @@ -4937,38 +5162,40 @@ 1153 @@ -4935,38 +5160,40 @@ static int leafReaderDataBytes(LeafReader *pReader){
1153 static const char *leafReaderData(LeafReader *pReader){ 1154 static const char *leafReaderData(LeafReader *pReader){
1154 int n, nData; 1155 int n, nData;
1155 assert( pReader->term.nData>0 ); 1156 assert( pReader->term.nData>0 );
1156 - n = getVarint32(pReader->pData, &nData); 1157 - n = getVarint32(pReader->pData, &nData);
1157 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData); 1158 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1158 + if( !n || nData>pReader->nData-n ) return NULL; 1159 + if( !n || nData>pReader->nData-n ) return NULL;
1159 return pReader->pData+n; 1160 return pReader->pData+n;
1160 } 1161 }
1161 1162
1162 -static void leafReaderInit(const char *pData, int nData, 1163 -static void leafReaderInit(const char *pData, int nData,
(...skipping 28 matching lines...) Expand all
1191 assert( !leafReaderAtEnd(pReader) ); 1192 assert( !leafReaderAtEnd(pReader) );
1192 1193
1193 /* Skip previous entry's data block. */ 1194 /* Skip previous entry's data block. */
1194 - n = getVarint32(pReader->pData, &nData); 1195 - n = getVarint32(pReader->pData, &nData);
1195 - assert( n+nData<=pReader->nData ); 1196 - assert( n+nData<=pReader->nData );
1196 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData); 1197 + n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
1197 + if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT; 1198 + if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT;
1198 pReader->pData += n+nData; 1199 pReader->pData += n+nData;
1199 pReader->nData -= n+nData; 1200 pReader->nData -= n+nData;
1200 1201
1201 @@ -4976,15 +5203,23 @@ 1202 @@ -4974,15 +5201,23 @@ static void leafReaderStep(LeafReader *pReader){
1202 /* Construct the new term using a prefix from the old term plus a 1203 /* Construct the new term using a prefix from the old term plus a
1203 ** suffix from the leaf data. 1204 ** suffix from the leaf data.
1204 */ 1205 */
1205 - n = getVarint32(pReader->pData, &nPrefix); 1206 - n = getVarint32(pReader->pData, &nPrefix);
1206 - n += getVarint32(pReader->pData+n, &nSuffix); 1207 - n += getVarint32(pReader->pData+n, &nSuffix);
1207 - assert( n+nSuffix<pReader->nData ); 1208 - assert( n+nSuffix<pReader->nData );
1208 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData); 1209 + n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
1209 + if( !n ) return SQLITE_CORRUPT_BKPT; 1210 + if( !n ) return SQLITE_CORRUPT_BKPT;
1210 + pReader->nData -= n; 1211 + pReader->nData -= n;
1211 + pReader->pData += n; 1212 + pReader->pData += n;
1212 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData); 1213 + n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
1213 + if( !n ) return SQLITE_CORRUPT_BKPT; 1214 + if( !n ) return SQLITE_CORRUPT_BKPT;
1214 + pReader->nData -= n; 1215 + pReader->nData -= n;
1215 + pReader->pData += n; 1216 + pReader->pData += n;
1216 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT; 1217 + if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
1217 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT; 1218 + if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
1218 pReader->term.nData = nPrefix; 1219 pReader->term.nData = nPrefix;
1219 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); 1220 - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
1220 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix); 1221 + dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
1221 1222
1222 - pReader->pData += n+nSuffix; 1223 - pReader->pData += n+nSuffix;
1223 - pReader->nData -= n+nSuffix; 1224 - pReader->nData -= n+nSuffix;
1224 + pReader->pData += nSuffix; 1225 + pReader->pData += nSuffix;
1225 + pReader->nData -= nSuffix; 1226 + pReader->nData -= nSuffix;
1226 } 1227 }
1227 + return SQLITE_OK; 1228 + return SQLITE_OK;
1228 } 1229 }
1229 1230
1230 /* strcmp-style comparison of pReader's current term against pTerm. 1231 /* strcmp-style comparison of pReader's current term against pTerm.
1231 @@ -5077,6 +5312,9 @@ 1232 @@ -5075,6 +5310,9 @@ static void leavesReaderDestroy(LeavesReader *pReader){
1232 ** the leaf data was entirely contained in the root), or from the 1233 ** the leaf data was entirely contained in the root), or from the
1233 ** stream of blocks between iStartBlockid and iEndBlockid, inclusive. 1234 ** stream of blocks between iStartBlockid and iEndBlockid, inclusive.
1234 */ 1235 */
1235 +/* TODO(shess): Figure out a means of indicating how many leaves are 1236 +/* TODO(shess): Figure out a means of indicating how many leaves are
1236 +** expected, for purposes of detecting corruption. 1237 +** expected, for purposes of detecting corruption.
1237 +*/ 1238 +*/
1238 static int leavesReaderInit(fulltext_vtab *v, 1239 static int leavesReaderInit(fulltext_vtab *v,
1239 int idx, 1240 int idx,
1240 sqlite_int64 iStartBlockid, 1241 sqlite_int64 iStartBlockid,
1241 @@ -5088,32 +5326,67 @@ 1242 @@ -5086,32 +5324,67 @@ static int leavesReaderInit(fulltext_vtab *v,
1242 1243
1243 dataBufferInit(&pReader->rootData, 0); 1244 dataBufferInit(&pReader->rootData, 0);
1244 if( iStartBlockid==0 ){ 1245 if( iStartBlockid==0 ){
1245 + int rc; 1246 + int rc;
1246 + /* Corrupt if this can't be a leaf node. */ 1247 + /* Corrupt if this can't be a leaf node. */
1247 + if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){ 1248 + if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){
1248 + return SQLITE_CORRUPT_BKPT; 1249 + return SQLITE_CORRUPT_BKPT;
1249 + } 1250 + }
1250 /* Entire leaf level fit in root data. */ 1251 /* Entire leaf level fit in root data. */
1251 dataBufferReplace(&pReader->rootData, pRootData, nRootData); 1252 dataBufferReplace(&pReader->rootData, pRootData, nRootData);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 } 1310 }
1310 - if( rc!=SQLITE_ROW ) return rc; 1311 - if( rc!=SQLITE_ROW ) return rc;
1311 1312
1312 pReader->pStmt = s; 1313 pReader->pStmt = s;
1313 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), 1314 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
1314 - sqlite3_column_bytes(pReader->pStmt, 0), 1315 - sqlite3_column_bytes(pReader->pStmt, 0),
1315 - &pReader->leafReader); 1316 - &pReader->leafReader);
1316 } 1317 }
1317 return SQLITE_OK; 1318 return SQLITE_OK;
1318 } 1319 }
1319 @@ -5122,11 +5395,12 @@ 1320 @@ -5120,11 +5393,12 @@ static int leavesReaderInit(fulltext_vtab *v,
1320 ** end of the current leaf, step forward to the next leaf block. 1321 ** end of the current leaf, step forward to the next leaf block.
1321 */ 1322 */
1322 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ 1323 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
1323 + int rc; 1324 + int rc;
1324 assert( !leavesReaderAtEnd(pReader) ); 1325 assert( !leavesReaderAtEnd(pReader) );
1325 - leafReaderStep(&pReader->leafReader); 1326 - leafReaderStep(&pReader->leafReader);
1326 + rc = leafReaderStep(&pReader->leafReader); 1327 + rc = leafReaderStep(&pReader->leafReader);
1327 + if( rc!=SQLITE_OK ) return rc; 1328 + if( rc!=SQLITE_OK ) return rc;
1328 1329
1329 if( leafReaderAtEnd(&pReader->leafReader) ){ 1330 if( leafReaderAtEnd(&pReader->leafReader) ){
1330 - int rc; 1331 - int rc;
1331 if( pReader->rootData.pData ){ 1332 if( pReader->rootData.pData ){
1332 pReader->eof = 1; 1333 pReader->eof = 1;
1333 return SQLITE_OK; 1334 return SQLITE_OK;
1334 @@ -5136,10 +5410,25 @@ 1335 @@ -5134,10 +5408,25 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesRead er *pReader){
1335 pReader->eof = 1; 1336 pReader->eof = 1;
1336 return rc==SQLITE_DONE ? SQLITE_OK : rc; 1337 return rc==SQLITE_DONE ? SQLITE_OK : rc;
1337 } 1338 }
1338 - leafReaderDestroy(&pReader->leafReader); 1339 - leafReaderDestroy(&pReader->leafReader);
1339 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), 1340 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
1340 - sqlite3_column_bytes(pReader->pStmt, 0), 1341 - sqlite3_column_bytes(pReader->pStmt, 0),
1341 - &pReader->leafReader); 1342 - &pReader->leafReader);
1342 + 1343 +
1343 + /* Corrupt if leaf data isn't a blob. */ 1344 + /* Corrupt if leaf data isn't a blob. */
1344 + if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){ 1345 + if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
1345 + return SQLITE_CORRUPT_BKPT; 1346 + return SQLITE_CORRUPT_BKPT;
1346 + }else{ 1347 + }else{
1347 + LeafReader tmp; 1348 + LeafReader tmp;
1348 + const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0); 1349 + const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0);
1349 + int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0); 1350 + int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0);
1350 + 1351 +
1351 + /* Corrupt if this can't be a leaf node. */ 1352 + /* Corrupt if this can't be a leaf node. */
1352 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){ 1353 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
1353 + return SQLITE_CORRUPT_BKPT; 1354 + return SQLITE_CORRUPT_BKPT;
1354 + } 1355 + }
1355 + 1356 +
1356 + rc = leafReaderInit(pLeafData, nLeafData, &tmp); 1357 + rc = leafReaderInit(pLeafData, nLeafData, &tmp);
1357 + if( rc!=SQLITE_OK ) return rc; 1358 + if( rc!=SQLITE_OK ) return rc;
1358 + leafReaderDestroy(&pReader->leafReader); 1359 + leafReaderDestroy(&pReader->leafReader);
1359 + pReader->leafReader = tmp; 1360 + pReader->leafReader = tmp;
1360 + } 1361 + }
1361 } 1362 }
1362 return SQLITE_OK; 1363 return SQLITE_OK;
1363 } 1364 }
1364 @@ -5200,8 +5489,19 @@ 1365 @@ -5198,8 +5487,19 @@ static int leavesReadersInit(fulltext_vtab *v, int iLevel ,
1365 sqlite_int64 iEnd = sqlite3_column_int64(s, 1); 1366 sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
1366 const char *pRootData = sqlite3_column_blob(s, 2); 1367 const char *pRootData = sqlite3_column_blob(s, 2);
1367 int nRootData = sqlite3_column_bytes(s, 2); 1368 int nRootData = sqlite3_column_bytes(s, 2);
1368 + sqlite_int64 iIndex = sqlite3_column_int64(s, 3); 1369 + sqlite_int64 iIndex = sqlite3_column_int64(s, 3);
1369 + 1370 +
1370 + /* Corrupt if we get back different types than we stored. */ 1371 + /* Corrupt if we get back different types than we stored. */
1371 + /* Also corrupt if the index is not sequential starting at 0. */ 1372 + /* Also corrupt if the index is not sequential starting at 0. */
1372 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER || 1373 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1373 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER || 1374 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1374 + sqlite3_column_type(s, 2)!=SQLITE_BLOB || 1375 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ||
1375 + i!=iIndex || 1376 + i!=iIndex ||
1376 + i>=MERGE_COUNT ){ 1377 + i>=MERGE_COUNT ){
1377 + rc = SQLITE_CORRUPT_BKPT; 1378 + rc = SQLITE_CORRUPT_BKPT;
1378 + break; 1379 + break;
1379 + } 1380 + }
1380 1381
1381 - assert( i<MERGE_COUNT ); 1382 - assert( i<MERGE_COUNT );
1382 rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData, 1383 rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData,
1383 &pReaders[i]); 1384 &pReaders[i]);
1384 if( rc!=SQLITE_OK ) break; 1385 if( rc!=SQLITE_OK ) break;
1385 @@ -5212,6 +5512,7 @@ 1386 @@ -5210,6 +5510,7 @@ static int leavesReadersInit(fulltext_vtab *v, int iLevel,
1386 while( i-->0 ){ 1387 while( i-->0 ){
1387 leavesReaderDestroy(&pReaders[i]); 1388 leavesReaderDestroy(&pReaders[i]);
1388 } 1389 }
1389 + sqlite3_reset(s); /* So we don't leave a lock. */ 1390 + sqlite3_reset(s); /* So we don't leave a lock. */
1390 return rc; 1391 return rc;
1391 } 1392 }
1392 1393
1393 @@ -5235,13 +5536,26 @@ 1394 @@ -5233,13 +5534,26 @@ static int leavesReadersMerge(fulltext_vtab *v,
1394 DLReader dlReaders[MERGE_COUNT]; 1395 DLReader dlReaders[MERGE_COUNT];
1395 const char *pTerm = leavesReaderTerm(pReaders); 1396 const char *pTerm = leavesReaderTerm(pReaders);
1396 int i, nTerm = leavesReaderTermBytes(pReaders); 1397 int i, nTerm = leavesReaderTermBytes(pReaders);
1397 + int rc; 1398 + int rc;
1398 1399
1399 assert( nReaders<=MERGE_COUNT ); 1400 assert( nReaders<=MERGE_COUNT );
1400 1401
1401 for(i=0; i<nReaders; i++){ 1402 for(i=0; i<nReaders; i++){
1402 - dlrInit(&dlReaders[i], DL_DEFAULT, 1403 - dlrInit(&dlReaders[i], DL_DEFAULT,
1403 - leavesReaderData(pReaders+i), 1404 - leavesReaderData(pReaders+i),
1404 - leavesReaderDataBytes(pReaders+i)); 1405 - leavesReaderDataBytes(pReaders+i));
1405 + const char *pData = leavesReaderData(pReaders+i); 1406 + const char *pData = leavesReaderData(pReaders+i);
1406 + if( pData==NULL ){ 1407 + if( pData==NULL ){
1407 + rc = SQLITE_CORRUPT_BKPT; 1408 + rc = SQLITE_CORRUPT_BKPT;
1408 + break; 1409 + break;
1409 + } 1410 + }
1410 + rc = dlrInit(&dlReaders[i], DL_DEFAULT, 1411 + rc = dlrInit(&dlReaders[i], DL_DEFAULT,
1411 + pData, 1412 + pData,
1412 + leavesReaderDataBytes(pReaders+i)); 1413 + leavesReaderDataBytes(pReaders+i));
1413 + if( rc!=SQLITE_OK ) break; 1414 + if( rc!=SQLITE_OK ) break;
1414 + } 1415 + }
1415 + if( rc!=SQLITE_OK ){ 1416 + if( rc!=SQLITE_OK ){
1416 + while( i-->0 ){ 1417 + while( i-->0 ){
1417 + dlrDestroy(&dlReaders[i]); 1418 + dlrDestroy(&dlReaders[i]);
1418 + } 1419 + }
1419 + return rc; 1420 + return rc;
1420 } 1421 }
1421 1422
1422 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders); 1423 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
1423 @@ -5295,10 +5609,14 @@ 1424 @@ -5293,10 +5607,14 @@ static int segmentMerge(fulltext_vtab *v, int iLevel){
1424 memset(&lrs, '\0', sizeof(lrs)); 1425 memset(&lrs, '\0', sizeof(lrs));
1425 rc = leavesReadersInit(v, iLevel, lrs, &i); 1426 rc = leavesReadersInit(v, iLevel, lrs, &i);
1426 if( rc!=SQLITE_OK ) return rc; 1427 if( rc!=SQLITE_OK ) return rc;
1427 - assert( i==MERGE_COUNT ); 1428 - assert( i==MERGE_COUNT );
1428 1429
1429 leafWriterInit(iLevel+1, idx, &writer); 1430 leafWriterInit(iLevel+1, idx, &writer);
1430 1431
1431 + if( i!=MERGE_COUNT ){ 1432 + if( i!=MERGE_COUNT ){
1432 + rc = SQLITE_CORRUPT_BKPT; 1433 + rc = SQLITE_CORRUPT_BKPT;
1433 + goto err; 1434 + goto err;
1434 + } 1435 + }
1435 + 1436 +
1436 /* Since leavesReaderReorder() pushes readers at eof to the end, 1437 /* Since leavesReaderReorder() pushes readers at eof to the end,
1437 ** when the first reader is empty, all will be empty. 1438 ** when the first reader is empty, all will be empty.
1438 */ 1439 */
1439 @@ -5341,12 +5659,14 @@ 1440 @@ -5339,12 +5657,14 @@ static int segmentMerge(fulltext_vtab *v, int iLevel){
1440 } 1441 }
1441 1442
1442 /* Accumulate the union of *acc and *pData into *acc. */ 1443 /* Accumulate the union of *acc and *pData into *acc. */
1443 -static void docListAccumulateUnion(DataBuffer *acc, 1444 -static void docListAccumulateUnion(DataBuffer *acc,
1444 - const char *pData, int nData) { 1445 - const char *pData, int nData) {
1445 +static int docListAccumulateUnion(DataBuffer *acc, 1446 +static int docListAccumulateUnion(DataBuffer *acc,
1446 + const char *pData, int nData) { 1447 + const char *pData, int nData) {
1447 DataBuffer tmp = *acc; 1448 DataBuffer tmp = *acc;
1448 + int rc; 1449 + int rc;
1449 dataBufferInit(acc, tmp.nData+nData); 1450 dataBufferInit(acc, tmp.nData+nData);
1450 - docListUnion(tmp.pData, tmp.nData, pData, nData, acc); 1451 - docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1451 + rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc); 1452 + rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
1452 dataBufferDestroy(&tmp); 1453 dataBufferDestroy(&tmp);
1453 + return rc; 1454 + return rc;
1454 } 1455 }
1455 1456
1456 /* TODO(shess) It might be interesting to explore different merge 1457 /* TODO(shess) It might be interesting to explore different merge
1457 @@ -5388,8 +5708,13 @@ 1458 @@ -5386,8 +5706,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesR eader *pReader,
1458 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); 1459 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
1459 if( c>0 ) break; /* Past any possible matches. */ 1460 if( c>0 ) break; /* Past any possible matches. */
1460 if( c==0 ){ 1461 if( c==0 ){
1461 + int iBuffer, nData; 1462 + int iBuffer, nData;
1462 const char *pData = leavesReaderData(pReader); 1463 const char *pData = leavesReaderData(pReader);
1463 - int iBuffer, nData = leavesReaderDataBytes(pReader); 1464 - int iBuffer, nData = leavesReaderDataBytes(pReader);
1464 + if( pData==NULL ){ 1465 + if( pData==NULL ){
1465 + rc = SQLITE_CORRUPT_BKPT; 1466 + rc = SQLITE_CORRUPT_BKPT;
1466 + break; 1467 + break;
1467 + } 1468 + }
1468 + nData = leavesReaderDataBytes(pReader); 1469 + nData = leavesReaderDataBytes(pReader);
1469 1470
1470 /* Find the first empty buffer. */ 1471 /* Find the first empty buffer. */
1471 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){ 1472 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
1472 @@ -5435,11 +5760,13 @@ 1473 @@ -5433,11 +5758,13 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, Leaves Reader *pReader,
1473 ** with pData/nData. 1474 ** with pData/nData.
1474 */ 1475 */
1475 dataBufferSwap(p, pAcc); 1476 dataBufferSwap(p, pAcc);
1476 - docListAccumulateUnion(pAcc, pData, nData); 1477 - docListAccumulateUnion(pAcc, pData, nData);
1477 + rc = docListAccumulateUnion(pAcc, pData, nData); 1478 + rc = docListAccumulateUnion(pAcc, pData, nData);
1478 + if( rc!=SQLITE_OK ) goto err; 1479 + if( rc!=SQLITE_OK ) goto err;
1479 1480
1480 /* Accumulate remaining doclists into pAcc. */ 1481 /* Accumulate remaining doclists into pAcc. */
1481 for(++p; p<pAcc; ++p){ 1482 for(++p; p<pAcc; ++p){
1482 - docListAccumulateUnion(pAcc, p->pData, p->nData); 1483 - docListAccumulateUnion(pAcc, p->pData, p->nData);
1483 + rc = docListAccumulateUnion(pAcc, p->pData, p->nData); 1484 + rc = docListAccumulateUnion(pAcc, p->pData, p->nData);
1484 + if( rc!=SQLITE_OK ) goto err; 1485 + if( rc!=SQLITE_OK ) goto err;
1485 1486
1486 /* dataBufferReset() could allow a large doclist to blow up 1487 /* dataBufferReset() could allow a large doclist to blow up
1487 ** our memory requirements. 1488 ** our memory requirements.
1488 @@ -5464,13 +5791,15 @@ 1489 @@ -5462,13 +5789,15 @@ static int loadSegmentLeavesInt(fulltext_vtab *v, Leaves Reader *pReader,
1489 if( out->nData==0 ){ 1490 if( out->nData==0 ){
1490 dataBufferSwap(out, &(pBuffers[iBuffer])); 1491 dataBufferSwap(out, &(pBuffers[iBuffer]));
1491 }else{ 1492 }else{
1492 - docListAccumulateUnion(out, pBuffers[iBuffer].pData, 1493 - docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1493 - pBuffers[iBuffer].nData); 1494 - pBuffers[iBuffer].nData);
1494 + rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData, 1495 + rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData,
1495 + pBuffers[iBuffer].nData); 1496 + pBuffers[iBuffer].nData);
1496 + if( rc!=SQLITE_OK ) break; 1497 + if( rc!=SQLITE_OK ) break;
1497 } 1498 }
1498 } 1499 }
1499 } 1500 }
1500 } 1501 }
1501 1502
1502 +err: 1503 +err:
1503 while( nBuffers-- ){ 1504 while( nBuffers-- ){
1504 dataBufferDestroy(&(pBuffers[nBuffers])); 1505 dataBufferDestroy(&(pBuffers[nBuffers]));
1505 } 1506 }
1506 @@ -5529,20 +5858,26 @@ 1507 @@ -5527,20 +5856,26 @@ static int loadSegmentLeaves(fulltext_vtab *v,
1507 ** node. Consider whether breaking symmetry is worthwhile. I suspect 1508 ** node. Consider whether breaking symmetry is worthwhile. I suspect
1508 ** it is not worthwhile. 1509 ** it is not worthwhile.
1509 */ 1510 */
1510 -static void getChildrenContaining(const char *pData, int nData, 1511 -static void getChildrenContaining(const char *pData, int nData,
1511 - const char *pTerm, int nTerm, int isPrefix, 1512 - const char *pTerm, int nTerm, int isPrefix,
1512 - sqlite_int64 *piStartChild, 1513 - sqlite_int64 *piStartChild,
1513 - sqlite_int64 *piEndChild){ 1514 - sqlite_int64 *piEndChild){
1514 +static int getChildrenContaining(const char *pData, int nData, 1515 +static int getChildrenContaining(const char *pData, int nData,
1515 + const char *pTerm, int nTerm, int isPrefix, 1516 + const char *pTerm, int nTerm, int isPrefix,
1516 + sqlite_int64 *piStartChild, 1517 + sqlite_int64 *piStartChild,
(...skipping 12 matching lines...) Expand all
1529 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; 1530 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
1530 - interiorReaderStep(&reader); 1531 - interiorReaderStep(&reader);
1531 + rc = interiorReaderStep(&reader); 1532 + rc = interiorReaderStep(&reader);
1532 + if( rc!=SQLITE_OK ){ 1533 + if( rc!=SQLITE_OK ){
1533 + interiorReaderDestroy(&reader); 1534 + interiorReaderDestroy(&reader);
1534 + return rc; 1535 + return rc;
1535 + } 1536 + }
1536 } 1537 }
1537 *piStartChild = interiorReaderCurrentBlockid(&reader); 1538 *piStartChild = interiorReaderCurrentBlockid(&reader);
1538 1539
1539 @@ -5552,7 +5887,11 @@ 1540 @@ -5550,7 +5885,11 @@ static void getChildrenContaining(const char *pData, int nData,
1540 */ 1541 */
1541 while( !interiorReaderAtEnd(&reader) ){ 1542 while( !interiorReaderAtEnd(&reader) ){
1542 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; 1543 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
1543 - interiorReaderStep(&reader); 1544 - interiorReaderStep(&reader);
1544 + rc = interiorReaderStep(&reader); 1545 + rc = interiorReaderStep(&reader);
1545 + if( rc!=SQLITE_OK ){ 1546 + if( rc!=SQLITE_OK ){
1546 + interiorReaderDestroy(&reader); 1547 + interiorReaderDestroy(&reader);
1547 + return rc; 1548 + return rc;
1548 + } 1549 + }
1549 } 1550 }
1550 *piEndChild = interiorReaderCurrentBlockid(&reader); 1551 *piEndChild = interiorReaderCurrentBlockid(&reader);
1551 1552
1552 @@ -5561,6 +5900,7 @@ 1553 @@ -5559,6 +5898,7 @@ static void getChildrenContaining(const char *pData, int n Data,
1553 /* Children must ascend, and if !prefix, both must be the same. */ 1554 /* Children must ascend, and if !prefix, both must be the same. */
1554 assert( *piEndChild>=*piStartChild ); 1555 assert( *piEndChild>=*piStartChild );
1555 assert( isPrefix || *piStartChild==*piEndChild ); 1556 assert( isPrefix || *piStartChild==*piEndChild );
1556 + return rc; 1557 + return rc;
1557 } 1558 }
1558 1559
1559 /* Read block at iBlockid and pass it with other params to 1560 /* Read block at iBlockid and pass it with other params to
1560 @@ -5588,11 +5928,31 @@ 1561 @@ -5586,11 +5926,31 @@ static int loadAndGetChildrenContaining(
1561 if( rc!=SQLITE_OK ) return rc; 1562 if( rc!=SQLITE_OK ) return rc;
1562 1563
1563 rc = sqlite3_step(s); 1564 rc = sqlite3_step(s);
1564 - if( rc==SQLITE_DONE ) return SQLITE_ERROR; 1565 - if( rc==SQLITE_DONE ) return SQLITE_ERROR;
1565 + /* Corrupt if interior node references missing child node. */ 1566 + /* Corrupt if interior node references missing child node. */
1566 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT; 1567 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
1567 if( rc!=SQLITE_ROW ) return rc; 1568 if( rc!=SQLITE_ROW ) return rc;
1568 1569
1569 - getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0), 1570 - getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
1570 - pTerm, nTerm, isPrefix, piStartChild, piEndChild); 1571 - pTerm, nTerm, isPrefix, piStartChild, piEndChild);
(...skipping 14 matching lines...) Expand all
1585 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, 1586 + rc = getChildrenContaining(pData, nData, pTerm, nTerm,
1586 + isPrefix, piStartChild, piEndChild); 1587 + isPrefix, piStartChild, piEndChild);
1587 + if( rc!=SQLITE_OK ){ 1588 + if( rc!=SQLITE_OK ){
1588 + sqlite3_reset(s); 1589 + sqlite3_reset(s);
1589 + return rc; 1590 + return rc;
1590 + } 1591 + }
1591 + } 1592 + }
1592 1593
1593 /* We expect only one row. We must execute another sqlite3_step() 1594 /* We expect only one row. We must execute another sqlite3_step()
1594 * to complete the iteration; otherwise the table will remain 1595 * to complete the iteration; otherwise the table will remain
1595 @@ -5622,8 +5982,9 @@ 1596 @@ -5620,8 +5980,9 @@ static int loadSegmentInt(fulltext_vtab *v, const char *pD ata, int nData,
1596 /* Process pData as an interior node, then loop down the tree 1597 /* Process pData as an interior node, then loop down the tree
1597 ** until we find the set of leaf nodes to scan for the term. 1598 ** until we find the set of leaf nodes to scan for the term.
1598 */ 1599 */
1599 - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, 1600 - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1600 - &iStartChild, &iEndChild); 1601 - &iStartChild, &iEndChild);
1601 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, 1602 + rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
1602 + &iStartChild, &iEndChild); 1603 + &iStartChild, &iEndChild);
1603 + if( rc!=SQLITE_OK ) return rc; 1604 + if( rc!=SQLITE_OK ) return rc;
1604 while( iStartChild>iLeavesEnd ){ 1605 while( iStartChild>iLeavesEnd ){
1605 sqlite_int64 iNextStart, iNextEnd; 1606 sqlite_int64 iNextStart, iNextEnd;
1606 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, 1607 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
1607 @@ -5675,7 +6036,8 @@ 1608 @@ -5673,7 +6034,8 @@ static int loadSegment(fulltext_vtab *v, const char *pData , int nData,
1608 DataBuffer result; 1609 DataBuffer result;
1609 int rc; 1610 int rc;
1610 1611
1611 - assert( nData>1 ); 1612 - assert( nData>1 );
1612 + /* Corrupt if segment root can't be valid. */ 1613 + /* Corrupt if segment root can't be valid. */
1613 + if( pData==NULL || nData<1 ) return SQLITE_CORRUPT_BKPT; 1614 + if( pData==NULL || nData<1 ) return SQLITE_CORRUPT_BKPT;
1614 1615
1615 /* This code should never be called with buffered updates. */ 1616 /* This code should never be called with buffered updates. */
1616 assert( v->nPendingData<0 ); 1617 assert( v->nPendingData<0 );
1617 @@ -5692,16 +6054,21 @@ 1618 @@ -5690,16 +6052,21 @@ static int loadSegment(fulltext_vtab *v, const char *pDa ta, int nData,
1618 DataBuffer merged; 1619 DataBuffer merged;
1619 DLReader readers[2]; 1620 DLReader readers[2];
1620 1621
1621 - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); 1622 - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1622 - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); 1623 - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1623 - dataBufferInit(&merged, out->nData+result.nData); 1624 - dataBufferInit(&merged, out->nData+result.nData);
1624 - docListMerge(&merged, readers, 2); 1625 - docListMerge(&merged, readers, 2);
1625 - dataBufferDestroy(out); 1626 - dataBufferDestroy(out);
1626 - *out = merged; 1627 - *out = merged;
1627 - dlrDestroy(&readers[0]); 1628 - dlrDestroy(&readers[0]);
1628 - dlrDestroy(&readers[1]); 1629 - dlrDestroy(&readers[1]);
1629 + rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); 1630 + rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
1630 + if( rc==SQLITE_OK ){ 1631 + if( rc==SQLITE_OK ){
1631 + rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); 1632 + rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
1632 + if( rc==SQLITE_OK ){ 1633 + if( rc==SQLITE_OK ){
1633 + dataBufferInit(&merged, out->nData+result.nData); 1634 + dataBufferInit(&merged, out->nData+result.nData);
1634 + rc = docListMerge(&merged, readers, 2); 1635 + rc = docListMerge(&merged, readers, 2);
1635 + dataBufferDestroy(out); 1636 + dataBufferDestroy(out);
1636 + *out = merged; 1637 + *out = merged;
1637 + dlrDestroy(&readers[1]); 1638 + dlrDestroy(&readers[1]);
1638 + } 1639 + }
1639 + dlrDestroy(&readers[0]); 1640 + dlrDestroy(&readers[0]);
1640 + } 1641 + }
1641 } 1642 }
1642 } 1643 }
1643 + 1644 +
1644 dataBufferDestroy(&result); 1645 dataBufferDestroy(&result);
1645 return rc; 1646 return rc;
1646 } 1647 }
1647 @@ -5729,11 +6096,20 @@ 1648 @@ -5727,11 +6094,20 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1648 const char *pData = sqlite3_column_blob(s, 2); 1649 const char *pData = sqlite3_column_blob(s, 2);
1649 const int nData = sqlite3_column_bytes(s, 2); 1650 const int nData = sqlite3_column_bytes(s, 2);
1650 const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1); 1651 const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
1651 + 1652 +
1652 + /* Corrupt if we get back different types than we stored. */ 1653 + /* Corrupt if we get back different types than we stored. */
1653 + if( sqlite3_column_type(s, 1)!=SQLITE_INTEGER || 1654 + if( sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1654 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){ 1655 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1655 + rc = SQLITE_CORRUPT_BKPT; 1656 + rc = SQLITE_CORRUPT_BKPT;
1656 + goto err; 1657 + goto err;
1657 + } 1658 + }
1658 + 1659 +
1659 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix, 1660 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
1660 &doclist); 1661 &doclist);
1661 if( rc!=SQLITE_OK ) goto err; 1662 if( rc!=SQLITE_OK ) goto err;
1662 } 1663 }
1663 if( rc==SQLITE_DONE ){ 1664 if( rc==SQLITE_DONE ){
1664 + rc = SQLITE_OK; 1665 + rc = SQLITE_OK;
1665 if( doclist.nData!=0 ){ 1666 if( doclist.nData!=0 ){
1666 /* TODO(shess) The old term_select_all() code applied the column 1667 /* TODO(shess) The old term_select_all() code applied the column
1667 ** restrict as we merged segments, leading to smaller buffers. 1668 ** restrict as we merged segments, leading to smaller buffers.
1668 @@ -5741,13 +6117,13 @@ 1669 @@ -5739,13 +6115,13 @@ static int termSelect(fulltext_vtab *v, int iColumn,
1669 ** system is checked in. 1670 ** system is checked in.
1670 */ 1671 */
1671 if( iColumn==v->nColumn) iColumn = -1; 1672 if( iColumn==v->nColumn) iColumn = -1;
1672 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1673 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1673 - iColumn, iType, out); 1674 - iColumn, iType, out);
1674 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1675 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1675 + iColumn, iType, out); 1676 + iColumn, iType, out);
1676 } 1677 }
1677 - rc = SQLITE_OK; 1678 - rc = SQLITE_OK;
1678 } 1679 }
1679 1680
1680 err: 1681 err:
1681 + sqlite3_reset(s); /* So we don't leave a lock. */ 1682 + sqlite3_reset(s); /* So we don't leave a lock. */
1682 dataBufferDestroy(&doclist); 1683 dataBufferDestroy(&doclist);
1683 return rc; 1684 return rc;
1684 } 1685 }
1685 @@ -6089,6 +6465,7 @@ 1686 @@ -6087,6 +6463,7 @@ static int optimizeInternal(fulltext_vtab *v,
1686 LeafWriter *pWriter){ 1687 LeafWriter *pWriter){
1687 int i, rc = SQLITE_OK; 1688 int i, rc = SQLITE_OK;
1688 DataBuffer doclist, merged, tmp; 1689 DataBuffer doclist, merged, tmp;
1689 + const char *pData; 1690 + const char *pData;
1690 1691
1691 /* Order the readers. */ 1692 /* Order the readers. */
1692 i = nReaders; 1693 i = nReaders;
1693 @@ -6109,14 +6486,21 @@ 1694 @@ -6107,14 +6484,21 @@ static int optimizeInternal(fulltext_vtab *v,
1694 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break; 1695 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
1695 } 1696 }
1696 1697
1697 + pData = optLeavesReaderData(&readers[0]); 1698 + pData = optLeavesReaderData(&readers[0]);
1698 + if( pData==NULL ){ 1699 + if( pData==NULL ){
1699 + rc = SQLITE_CORRUPT_BKPT; 1700 + rc = SQLITE_CORRUPT_BKPT;
1700 + break; 1701 + break;
1701 + } 1702 + }
1702 + 1703 +
1703 /* Special-case for no merge. */ 1704 /* Special-case for no merge. */
1704 if( i==1 ){ 1705 if( i==1 ){
1705 /* Trim deletions from the doclist. */ 1706 /* Trim deletions from the doclist. */
1706 dataBufferReset(&merged); 1707 dataBufferReset(&merged);
1707 - docListTrim(DL_DEFAULT, 1708 - docListTrim(DL_DEFAULT,
1708 - optLeavesReaderData(&readers[0]), 1709 - optLeavesReaderData(&readers[0]),
1709 - optLeavesReaderDataBytes(&readers[0]), 1710 - optLeavesReaderDataBytes(&readers[0]),
1710 - -1, DL_DEFAULT, &merged); 1711 - -1, DL_DEFAULT, &merged);
1711 + rc = docListTrim(DL_DEFAULT, 1712 + rc = docListTrim(DL_DEFAULT,
1712 + pData, 1713 + pData,
1713 + optLeavesReaderDataBytes(&readers[0]), 1714 + optLeavesReaderDataBytes(&readers[0]),
1714 + -1, DL_DEFAULT, &merged); 1715 + -1, DL_DEFAULT, &merged);
1715 + if( rc!= SQLITE_OK ) break; 1716 + if( rc!= SQLITE_OK ) break;
1716 }else{ 1717 }else{
1717 DLReader dlReaders[MERGE_COUNT]; 1718 DLReader dlReaders[MERGE_COUNT];
1718 int iReader, nReaders; 1719 int iReader, nReaders;
1719 @@ -6124,9 +6508,10 @@ 1720 @@ -6122,9 +6506,10 @@ static int optimizeInternal(fulltext_vtab *v,
1720 /* Prime the pipeline with the first reader's doclist. After 1721 /* Prime the pipeline with the first reader's doclist. After
1721 ** one pass index 0 will reference the accumulated doclist. 1722 ** one pass index 0 will reference the accumulated doclist.
1722 */ 1723 */
1723 - dlrInit(&dlReaders[0], DL_DEFAULT, 1724 - dlrInit(&dlReaders[0], DL_DEFAULT,
1724 - optLeavesReaderData(&readers[0]), 1725 - optLeavesReaderData(&readers[0]),
1725 - optLeavesReaderDataBytes(&readers[0])); 1726 - optLeavesReaderDataBytes(&readers[0]));
1726 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, 1727 + rc = dlrInit(&dlReaders[0], DL_DEFAULT,
1727 + pData, 1728 + pData,
1728 + optLeavesReaderDataBytes(&readers[0])); 1729 + optLeavesReaderDataBytes(&readers[0]));
1729 + if( rc!=SQLITE_OK ) break; 1730 + if( rc!=SQLITE_OK ) break;
1730 iReader = 1; 1731 iReader = 1;
1731 1732
1732 assert( iReader<i ); /* Must execute the loop at least once. */ 1733 assert( iReader<i ); /* Must execute the loop at least once. */
1733 @@ -6134,24 +6519,35 @@ 1734 @@ -6132,24 +6517,35 @@ static int optimizeInternal(fulltext_vtab *v,
1734 /* Merge 16 inputs per pass. */ 1735 /* Merge 16 inputs per pass. */
1735 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT; 1736 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
1736 iReader++, nReaders++ ){ 1737 iReader++, nReaders++ ){
1737 - dlrInit(&dlReaders[nReaders], DL_DEFAULT, 1738 - dlrInit(&dlReaders[nReaders], DL_DEFAULT,
1738 - optLeavesReaderData(&readers[iReader]), 1739 - optLeavesReaderData(&readers[iReader]),
1739 - optLeavesReaderDataBytes(&readers[iReader])); 1740 - optLeavesReaderDataBytes(&readers[iReader]));
1740 + pData = optLeavesReaderData(&readers[iReader]); 1741 + pData = optLeavesReaderData(&readers[iReader]);
1741 + if( pData == NULL ){ 1742 + if( pData == NULL ){
1742 + rc = SQLITE_CORRUPT_BKPT; 1743 + rc = SQLITE_CORRUPT_BKPT;
1743 + break; 1744 + break;
(...skipping 24 matching lines...) Expand all
1768 1769
1769 + if( rc!=SQLITE_OK ) goto err; 1770 + if( rc!=SQLITE_OK ) goto err;
1770 + 1771 +
1771 /* Accumulated doclist to reader 0 for next pass. */ 1772 /* Accumulated doclist to reader 0 for next pass. */
1772 - dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); 1773 - dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1773 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); 1774 + rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
1774 + if( rc!=SQLITE_OK ) goto err; 1775 + if( rc!=SQLITE_OK ) goto err;
1775 } 1776 }
1776 1777
1777 /* Destroy reader that was left in the pipeline. */ 1778 /* Destroy reader that was left in the pipeline. */
1778 @@ -6159,8 +6555,9 @@ 1779 @@ -6157,8 +6553,9 @@ static int optimizeInternal(fulltext_vtab *v,
1779 1780
1780 /* Trim deletions from the doclist. */ 1781 /* Trim deletions from the doclist. */
1781 dataBufferReset(&merged); 1782 dataBufferReset(&merged);
1782 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1783 - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1783 - -1, DL_DEFAULT, &merged); 1784 - -1, DL_DEFAULT, &merged);
1784 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 1785 + rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
1785 + -1, DL_DEFAULT, &merged); 1786 + -1, DL_DEFAULT, &merged);
1786 + if( rc!=SQLITE_OK ) goto err; 1787 + if( rc!=SQLITE_OK ) goto err;
1787 } 1788 }
1788 1789
1789 /* Only pass doclists with hits (skip if all hits deleted). */ 1790 /* Only pass doclists with hits (skip if all hits deleted). */
1790 @@ -6240,6 +6637,14 @@ 1791 @@ -6238,6 +6635,14 @@ static void optimizeFunc(sqlite3_context *pContext,
1791 const char *pRootData = sqlite3_column_blob(s, 2); 1792 const char *pRootData = sqlite3_column_blob(s, 2);
1792 int nRootData = sqlite3_column_bytes(s, 2); 1793 int nRootData = sqlite3_column_bytes(s, 2);
1793 1794
1794 + /* Corrupt if we get back different types than we stored. */ 1795 + /* Corrupt if we get back different types than we stored. */
1795 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER || 1796 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1796 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER || 1797 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1797 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){ 1798 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1798 + rc = SQLITE_CORRUPT_BKPT; 1799 + rc = SQLITE_CORRUPT_BKPT;
1799 + break; 1800 + break;
1800 + } 1801 + }
1801 + 1802 +
1802 assert( i<nReaders ); 1803 assert( i<nReaders );
1803 rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData, 1804 rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
1804 &readers[i].reader); 1805 &readers[i].reader);
1805 @@ -6253,6 +6658,8 @@ 1806 @@ -6251,6 +6656,8 @@ static void optimizeFunc(sqlite3_context *pContext,
1806 if( rc==SQLITE_DONE ){ 1807 if( rc==SQLITE_DONE ){
1807 assert( i==nReaders ); 1808 assert( i==nReaders );
1808 rc = optimizeInternal(v, readers, nReaders, &writer); 1809 rc = optimizeInternal(v, readers, nReaders, &writer);
1809 + }else{ 1810 + }else{
1810 + sqlite3_reset(s); /* So we don't leave a lock. */ 1811 + sqlite3_reset(s); /* So we don't leave a lock. */
1811 } 1812 }
1812 1813
1813 while( i-- > 0 ){ 1814 while( i-- > 0 ){
1814 @@ -6316,9 +6723,18 @@ 1815 @@ -6314,9 +6721,18 @@ static int collectSegmentTerms(fulltext_vtab *v, sqlite3_ stmt *s,
1815 const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1); 1816 const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1);
1816 const char *pRootData = sqlite3_column_blob(s, 2); 1817 const char *pRootData = sqlite3_column_blob(s, 2);
1817 const int nRootData = sqlite3_column_bytes(s, 2); 1818 const int nRootData = sqlite3_column_bytes(s, 2);
1818 + int rc; 1819 + int rc;
1819 LeavesReader reader; 1820 LeavesReader reader;
1820 - int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid, 1821 - int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
1821 - pRootData, nRootData, &reader); 1822 - pRootData, nRootData, &reader);
1822 + 1823 +
1823 + /* Corrupt if we get back different types than we stored. */ 1824 + /* Corrupt if we get back different types than we stored. */
1824 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER || 1825 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
1825 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER || 1826 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
1826 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){ 1827 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
1827 + return SQLITE_CORRUPT_BKPT; 1828 + return SQLITE_CORRUPT_BKPT;
1828 + } 1829 + }
1829 + 1830 +
1830 + rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid, 1831 + rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
1831 + pRootData, nRootData, &reader); 1832 + pRootData, nRootData, &reader);
1832 if( rc!=SQLITE_OK ) return rc; 1833 if( rc!=SQLITE_OK ) return rc;
1833 1834
1834 while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){ 1835 while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){
1835 @@ -6480,16 +6896,19 @@ 1836 @@ -6478,16 +6894,19 @@ static void createDoclistResult(sqlite3_context *pContex t,
1836 const char *pData, int nData){ 1837 const char *pData, int nData){
1837 DataBuffer dump; 1838 DataBuffer dump;
1838 DLReader dlReader; 1839 DLReader dlReader;
1839 + int rc; 1840 + int rc;
1840 1841
1841 assert( pData!=NULL && nData>0 ); 1842 assert( pData!=NULL && nData>0 );
1842 1843
1843 + rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData); 1844 + rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1844 + if( rc!=SQLITE_OK ) return rc; 1845 + if( rc!=SQLITE_OK ) return rc;
1845 dataBufferInit(&dump, 0); 1846 dataBufferInit(&dump, 0);
1846 - dlrInit(&dlReader, DL_DEFAULT, pData, nData); 1847 - dlrInit(&dlReader, DL_DEFAULT, pData, nData);
1847 - for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){ 1848 - for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
1848 + for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){ 1849 + for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){
1849 char buf[256]; 1850 char buf[256];
1850 PLReader plReader; 1851 PLReader plReader;
1851 1852
1852 - plrInit(&plReader, &dlReader); 1853 - plrInit(&plReader, &dlReader);
1853 + rc = plrInit(&plReader, &dlReader); 1854 + rc = plrInit(&plReader, &dlReader);
1854 + if( rc!=SQLITE_OK ) break; 1855 + if( rc!=SQLITE_OK ) break;
1855 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){ 1856 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
1856 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader)); 1857 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
1857 dataBufferAppend(&dump, buf, strlen(buf)); 1858 dataBufferAppend(&dump, buf, strlen(buf));
1858 @@ -6500,7 +6919,8 @@ 1859 @@ -6498,7 +6917,8 @@ static void createDoclistResult(sqlite3_context *pContext,
1859 dlrDocid(&dlReader), iColumn); 1860 dlrDocid(&dlReader), iColumn);
1860 dataBufferAppend(&dump, buf, strlen(buf)); 1861 dataBufferAppend(&dump, buf, strlen(buf));
1861 1862
1862 - for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){ 1863 - for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){
1863 + for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){ 1864 + for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){
1864 + if( rc!=SQLITE_OK ) break; 1865 + if( rc!=SQLITE_OK ) break;
1865 if( plrColumn(&plReader)!=iColumn ){ 1866 if( plrColumn(&plReader)!=iColumn ){
1866 iColumn = plrColumn(&plReader); 1867 iColumn = plrColumn(&plReader);
1867 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn); 1868 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
1868 @@ -6521,6 +6941,7 @@ 1869 @@ -6519,6 +6939,7 @@ static void createDoclistResult(sqlite3_context *pContext,
1869 dataBufferAppend(&dump, buf, strlen(buf)); 1870 dataBufferAppend(&dump, buf, strlen(buf));
1870 } 1871 }
1871 plrDestroy(&plReader); 1872 plrDestroy(&plReader);
1872 + if( rc!= SQLITE_OK ) break; 1873 + if( rc!= SQLITE_OK ) break;
1873 1874
1874 assert( dump.nData>0 ); 1875 assert( dump.nData>0 );
1875 dump.nData--; /* Overwrite trailing space. */ 1876 dump.nData--; /* Overwrite trailing space. */
1876 @@ -6529,6 +6950,10 @@ 1877 @@ -6527,6 +6948,10 @@ static void createDoclistResult(sqlite3_context *pContext ,
1877 } 1878 }
1878 } 1879 }
1879 dlrDestroy(&dlReader); 1880 dlrDestroy(&dlReader);
1880 + if( rc!=SQLITE_OK ){ 1881 + if( rc!=SQLITE_OK ){
1881 + dataBufferDestroy(&dump); 1882 + dataBufferDestroy(&dump);
1882 + return rc; 1883 + return rc;
1883 + } 1884 + }
1884 1885
1885 assert( dump.nData>0 ); 1886 assert( dump.nData>0 );
1886 dump.nData--; /* Overwrite trailing space. */ 1887 dump.nData--; /* Overwrite trailing space. */
1887 @@ -6540,6 +6965,7 @@ 1888 @@ -6538,6 +6963,7 @@ static void createDoclistResult(sqlite3_context *pContext,
1888 sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free); 1889 sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free);
1889 dump.pData = NULL; 1890 dump.pData = NULL;
1890 dump.nData = dump.nCapacity = 0; 1891 dump.nData = dump.nCapacity = 0;
1891 + return SQLITE_OK; 1892 + return SQLITE_OK;
1892 } 1893 }
1893 1894
1894 /* Implements dump_doclist() for use in inspecting the fts2 index from 1895 /* Implements dump_doclist() for use in inspecting the fts2 index from
1895 @@ -6822,7 +7248,11 @@ 1896 @@ -6820,7 +7246,11 @@ int sqlite3Fts2Init(sqlite3 *db){
1896 ** module with sqlite. 1897 ** module with sqlite.
1897 */ 1898 */
1898 if( SQLITE_OK==rc 1899 if( SQLITE_OK==rc
1899 +#if GEARS_FTS2_CHANGES && !SQLITE_TEST 1900 +#if GEARS_FTS2_CHANGES && !SQLITE_TEST
1900 + /* fts2_tokenizer() disabled for security reasons. */ 1901 + /* fts2_tokenizer() disabled for security reasons. */
1901 +#else 1902 +#else
1902 && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer")) 1903 && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer"))
1903 +#endif 1904 +#endif
1904 && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) 1905 && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
1905 && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1)) 1906 && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1))
1906 && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1)) 1907 && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1))
1907 diff -ru ext-orig/fts2/fts2_icu.c ext/fts2/fts2_icu.c 1908 diff --git a/third_party/sqlite/src/ext/fts2/fts2_icu.c b/third_party/sqlite/src /ext/fts2/fts2_icu.c
1908 --- ext-orig/fts2/fts2_icu.c» 2009-09-03 13:32:06.000000000 -0700 1909 index de8e116..6b9687e 100644
1909 +++ ext/fts2/fts2_icu.c»2009-09-18 14:39:41.000000000 -0700 1910 --- a/third_party/sqlite/src/ext/fts2/fts2_icu.c
1910 @@ -198,7 +198,7 @@ 1911 +++ b/third_party/sqlite/src/ext/fts2/fts2_icu.c
1912 @@ -198,7 +198,7 @@ static int icuNext(
1911 1913
1912 while( iStart<iEnd ){ 1914 while( iStart<iEnd ){
1913 int iWhite = iStart; 1915 int iWhite = iStart;
1914 - U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c); 1916 - U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
1915 + U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c); 1917 + U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
1916 if( u_isspace(c) ){ 1918 if( u_isspace(c) ){
1917 iStart = iWhite; 1919 iStart = iWhite;
1918 }else{ 1920 }else{
1919 diff -ru ext-orig/fts2/fts2_tokenizer.c ext/fts2/fts2_tokenizer.c 1921 diff --git a/third_party/sqlite/src/ext/fts2/fts2_tokenizer.c b/third_party/sqli te/src/ext/fts2/fts2_tokenizer.c
1920 --- ext-orig/fts2/fts2_tokenizer.c» 2009-09-03 13:32:06.000000000 -0700 1922 index f8b0663..00ed365 100644
1921 +++ ext/fts2/fts2_tokenizer.c» 2009-09-18 14:39:41.000000000 -0700 1923 --- a/third_party/sqlite/src/ext/fts2/fts2_tokenizer.c
1922 @@ -33,6 +33,7 @@ 1924 +++ b/third_party/sqlite/src/ext/fts2/fts2_tokenizer.c
1925 @@ -33,6 +33,7 @@ SQLITE_EXTENSION_INIT1
1923 #include "fts2_hash.h" 1926 #include "fts2_hash.h"
1924 #include "fts2_tokenizer.h" 1927 #include "fts2_tokenizer.h"
1925 #include <assert.h> 1928 #include <assert.h>
1926 +#include <stddef.h> 1929 +#include <stddef.h>
1927 1930
1928 /* 1931 /*
1929 ** Implementation of the SQL scalar function for accessing the underlying 1932 ** 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/fts3.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698