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

Side by Side Diff: third_party/sqlite/patches/0022-fts2-Detect-and-handle-certain-corruption-cases.patch

Issue 885473002: [sql] Rewrite sqlite patching "system". (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 From ddbd1f830c4000b17617b917a768ea4a4ad8d660 Mon Sep 17 00:00:00 2001
2 From: Scott Hess <shess@chromium.org>
3 Date: Mon, 22 Dec 2014 16:57:47 -0800
4 Subject: [PATCH 22/24] [fts2] Detect and handle certain corruption cases.
5
6 These were in response to actual corrupt databases found in the wild.
7
8 Original Gears CL:
9 https://code.google.com/p/gears/source/detail?r=2855&path=/trunk/third_party/sql ite_google/ext/fts2/fts2.c
10 ---
11 third_party/sqlite/src/ext/fts2/fts2.c | 152 ++++++++++++++++++++++++++++-----
12 1 file changed, 132 insertions(+), 20 deletions(-)
13
14 diff --git a/third_party/sqlite/src/ext/fts2/fts2.c b/third_party/sqlite/src/ext /fts2/fts2.c
15 index 7d07137..bdbd747 100644
16 --- a/third_party/sqlite/src/ext/fts2/fts2.c
17 +++ b/third_party/sqlite/src/ext/fts2/fts2.c
18 @@ -349,6 +349,16 @@
19 # define TRACE(A)
20 #endif
21
22 +#if 0
23 +/* Useful to set breakpoints. See main.c sqlite3Corrupt(). */
24 +static int fts2Corrupt(void){
25 + return SQLITE_CORRUPT;
26 +}
27 +# define SQLITE_CORRUPT_BKPT fts2Corrupt()
28 +#else
29 +# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
30 +#endif
31 +
32 /* It is not safe to call isspace(), tolower(), or isalnum() on
33 ** hi-bit-set characters. This is the same solution used in the
34 ** tokenizer.
35 @@ -3435,8 +3445,11 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){
36 c->eof = 0;
37 return SQLITE_OK;
38 }
39 - /* an error occurred; abort */
40 - return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
41 +
42 + /* Corrupt if the index refers to missing document. */
43 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
44 +
45 + return rc;
46 }
47 }
48
49 @@ -5106,6 +5119,9 @@ static void leavesReaderDestroy(LeavesReader *pReader){
50 ** the leaf data was entirely contained in the root), or from the
51 ** stream of blocks between iStartBlockid and iEndBlockid, inclusive.
52 */
53 +/* TODO(shess): Figure out a means of indicating how many leaves are
54 +** expected, for purposes of detecting corruption.
55 +*/
56 static int leavesReaderInit(fulltext_vtab *v,
57 int idx,
58 sqlite_int64 iStartBlockid,
59 @@ -5117,6 +5133,10 @@ static int leavesReaderInit(fulltext_vtab *v,
60
61 dataBufferInit(&pReader->rootData, 0);
62 if( iStartBlockid==0 ){
63 + /* Corrupt if this can't be a leaf node. */
64 + if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){
65 + return SQLITE_CORRUPT_BKPT;
66 + }
67 /* Entire leaf level fit in root data. */
68 dataBufferReplace(&pReader->rootData, pRootData, nRootData);
69 leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
70 @@ -5127,22 +5147,48 @@ static int leavesReaderInit(fulltext_vtab *v,
71 if( rc!=SQLITE_OK ) return rc;
72
73 rc = sqlite3_bind_int64(s, 1, iStartBlockid);
74 - if( rc!=SQLITE_OK ) return rc;
75 + if( rc!=SQLITE_OK ) goto err;
76
77 rc = sqlite3_bind_int64(s, 2, iEndBlockid);
78 - if( rc!=SQLITE_OK ) return rc;
79 + if( rc!=SQLITE_OK ) goto err;
80
81 rc = sqlite3_step(s);
82 +
83 + /* Corrupt if interior node referenced missing leaf node. */
84 if( rc==SQLITE_DONE ){
85 - pReader->eof = 1;
86 - return SQLITE_OK;
87 + rc = SQLITE_CORRUPT_BKPT;
88 + goto err;
89 + }
90 +
91 + if( rc!=SQLITE_ROW ) goto err;
92 + rc = SQLITE_OK;
93 +
94 + /* Corrupt if leaf data isn't a blob. */
95 + if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){
96 + rc = SQLITE_CORRUPT_BKPT;
97 + }else{
98 + const char *pLeafData = sqlite3_column_blob(s, 0);
99 + int nLeafData = sqlite3_column_bytes(s, 0);
100 +
101 + /* Corrupt if this can't be a leaf node. */
102 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
103 + rc = SQLITE_CORRUPT_BKPT;
104 + }else{
105 + leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
106 + }
107 + }
108 +
109 + err:
110 + if( rc!=SQLITE_OK ){
111 + if( idx==-1 ){
112 + sqlite3_finalize(s);
113 + }else{
114 + sqlite3_reset(s);
115 + }
116 + return rc;
117 }
118 - if( rc!=SQLITE_ROW ) return rc;
119
120 pReader->pStmt = s;
121 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
122 - sqlite3_column_bytes(pReader->pStmt, 0),
123 - &pReader->leafReader);
124 }
125 return SQLITE_OK;
126 }
127 @@ -5165,10 +5211,22 @@ static int leavesReaderStep(fulltext_vtab *v, LeavesRead er *pReader){
128 pReader->eof = 1;
129 return rc==SQLITE_DONE ? SQLITE_OK : rc;
130 }
131 - leafReaderDestroy(&pReader->leafReader);
132 - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
133 - sqlite3_column_bytes(pReader->pStmt, 0),
134 - &pReader->leafReader);
135 +
136 + /* Corrupt if leaf data isn't a blob. */
137 + if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
138 + return SQLITE_CORRUPT_BKPT;
139 + }else{
140 + const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0);
141 + int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0);
142 +
143 + /* Corrupt if this can't be a leaf node. */
144 + if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
145 + return SQLITE_CORRUPT_BKPT;
146 + }
147 +
148 + leafReaderDestroy(&pReader->leafReader);
149 + leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
150 + }
151 }
152 return SQLITE_OK;
153 }
154 @@ -5230,6 +5288,14 @@ static int leavesReadersInit(fulltext_vtab *v, int iLevel ,
155 const char *pRootData = sqlite3_column_blob(s, 2);
156 int nRootData = sqlite3_column_bytes(s, 2);
157
158 + /* Corrupt if we get back different types than we stored. */
159 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
160 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
161 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
162 + rc = SQLITE_CORRUPT_BKPT;
163 + break;
164 + }
165 +
166 assert( i<MERGE_COUNT );
167 rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData,
168 &pReaders[i]);
169 @@ -5241,6 +5307,7 @@ static int leavesReadersInit(fulltext_vtab *v, int iLevel,
170 while( i-->0 ){
171 leavesReaderDestroy(&pReaders[i]);
172 }
173 + sqlite3_reset(s); /* So we don't leave a lock. */
174 return rc;
175 }
176
177 @@ -5617,11 +5684,27 @@ static int loadAndGetChildrenContaining(
178 if( rc!=SQLITE_OK ) return rc;
179
180 rc = sqlite3_step(s);
181 - if( rc==SQLITE_DONE ) return SQLITE_ERROR;
182 + /* Corrupt if interior node references missing child node. */
183 + if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
184 if( rc!=SQLITE_ROW ) return rc;
185
186 - getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
187 - pTerm, nTerm, isPrefix, piStartChild, piEndChild);
188 + /* Corrupt if child node isn't a blob. */
189 + if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){
190 + sqlite3_reset(s); /* So we don't leave a lock. */
191 + return SQLITE_CORRUPT_BKPT;
192 + }else{
193 + const char *pData = sqlite3_column_blob(s, 0);
194 + int nData = sqlite3_column_bytes(s, 0);
195 +
196 + /* Corrupt if child is not a valid interior node. */
197 + if( pData==NULL || nData<1 || pData[0]=='\0' ){
198 + sqlite3_reset(s); /* So we don't leave a lock. */
199 + return SQLITE_CORRUPT_BKPT;
200 + }
201 +
202 + getChildrenContaining(pData, nData, pTerm, nTerm,
203 + isPrefix, piStartChild, piEndChild);
204 + }
205
206 /* We expect only one row. We must execute another sqlite3_step()
207 * to complete the iteration; otherwise the table will remain
208 @@ -5704,7 +5787,8 @@ static int loadSegment(fulltext_vtab *v, const char *pData , int nData,
209 DataBuffer result;
210 int rc;
211
212 - assert( nData>1 );
213 + /* Corrupt if segment root can't be valid. */
214 + if( pData==NULL || nData<1 ) return SQLITE_CORRUPT_BKPT;
215
216 /* This code should never be called with buffered updates. */
217 assert( v->nPendingData<0 );
218 @@ -5758,6 +5842,14 @@ static int termSelect(fulltext_vtab *v, int iColumn,
219 const char *pData = sqlite3_column_blob(s, 2);
220 const int nData = sqlite3_column_bytes(s, 2);
221 const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
222 +
223 + /* Corrupt if we get back different types than we stored. */
224 + if( sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
225 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
226 + rc = SQLITE_CORRUPT_BKPT;
227 + goto err;
228 + }
229 +
230 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
231 &doclist);
232 if( rc!=SQLITE_OK ) goto err;
233 @@ -5777,6 +5869,7 @@ static int termSelect(fulltext_vtab *v, int iColumn,
234 }
235
236 err:
237 + sqlite3_reset(s); /* So we don't leave a lock. */
238 dataBufferDestroy(&doclist);
239 return rc;
240 }
241 @@ -6269,6 +6362,14 @@ static void optimizeFunc(sqlite3_context *pContext,
242 const char *pRootData = sqlite3_column_blob(s, 2);
243 int nRootData = sqlite3_column_bytes(s, 2);
244
245 + /* Corrupt if we get back different types than we stored. */
246 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
247 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
248 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
249 + rc = SQLITE_CORRUPT_BKPT;
250 + break;
251 + }
252 +
253 assert( i<nReaders );
254 rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
255 &readers[i].reader);
256 @@ -6282,6 +6383,8 @@ static void optimizeFunc(sqlite3_context *pContext,
257 if( rc==SQLITE_DONE ){
258 assert( i==nReaders );
259 rc = optimizeInternal(v, readers, nReaders, &writer);
260 + }else{
261 + sqlite3_reset(s); /* So we don't leave a lock. */
262 }
263
264 while( i-- > 0 ){
265 @@ -6345,9 +6448,18 @@ static int collectSegmentTerms(fulltext_vtab *v, sqlite3_ stmt *s,
266 const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1);
267 const char *pRootData = sqlite3_column_blob(s, 2);
268 const int nRootData = sqlite3_column_bytes(s, 2);
269 + int rc;
270 LeavesReader reader;
271 - int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
272 - pRootData, nRootData, &reader);
273 +
274 + /* Corrupt if we get back different types than we stored. */
275 + if( sqlite3_column_type(s, 0)!=SQLITE_INTEGER ||
276 + sqlite3_column_type(s, 1)!=SQLITE_INTEGER ||
277 + sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
278 + return SQLITE_CORRUPT_BKPT;
279 + }
280 +
281 + rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
282 + pRootData, nRootData, &reader);
283 if( rc!=SQLITE_OK ) return rc;
284
285 while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){
286 --
287 2.2.1
288
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698