OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |