diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-29 05:06:41 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-29 05:06:41 +0000 |
commit | 0d811a4265bbd36a7af8b09920ceb17348832200 (patch) | |
tree | d346d8674116855dea993c264e176d0c9a50b444 | |
parent | ad3c649648d61dd03304bd964e3e3b444c042933 (diff) | |
download | chromium_src-0d811a4265bbd36a7af8b09920ceb17348832200.zip chromium_src-0d811a4265bbd36a7af8b09920ceb17348832200.tar.gz chromium_src-0d811a4265bbd36a7af8b09920ceb17348832200.tar.bz2 |
[sql] Fix leafCursorCellDecode() crash.
If sqlite_master lists a valid root page for the table, and the root
page is an interior b-tree page, and none of the children are valid
pages, then recoverOpen() gets to leafCursorCreate(), and:
- leafCursorLoadPage() loads the page as an interior node into a parent
of the leaf cursor.
- leafCursorNextPage() returns SQLITE_DONE because no more pages are
available.
- SQLITE_OK is returned, but pCursor->pPage is left empty.
Then recoverFilter() calls leafCursorCellDecode(), which attempts to
access pCursor->pPage->pgno, where pPage is NULL and pgno is at offset
12, causing a crash accessing 0x0000000c.
The fix handles this by using bEOF to signal no data. This matches what
would happen if there were valid leaf pages which contained no valid
rows (recoverFilter() would call recoverNext() which would see
SQLITE_DONE from leafCursorNextValidCall(), set bEOF, and return
SQLITE_OK).
Reverts r241341, a diagnostic which is no longer necessary.
BUG=326646,329302
TBR=michaeln@chromium.org
Review URL: https://codereview.chromium.org/116853004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242701 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | third_party/sqlite/amalgamation/sqlite3.c | 16 | ||||
-rw-r--r-- | third_party/sqlite/src/src/recover.c | 16 |
2 files changed, 28 insertions, 4 deletions
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index ceaa966..5dfdd2c 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c @@ -111873,6 +111873,12 @@ static int recoverOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ pCursor->pLeafCursor = pLeafCursor; pCursor->iEncoding = iEncoding; + /* If no leaf pages were found, empty result set. */ + /* TODO(shess): leafCursorNextValidCell() would return SQLITE_ROW or + * SQLITE_DONE to indicate whether there is further data to consider. + */ + pCursor->bEOF = (pLeafCursor->pPage==NULL); + *ppCursor = (sqlite3_vtab_cursor*)pCursor; return SQLITE_OK; } @@ -111961,8 +111967,14 @@ static int recoverFilter( FNENTRY(); - /* Load the first cell, and iterate forward if it's not valid. */ - /* TODO(shess): What happens if no cells at all are valid? */ + /* There were no valid leaf pages in the table. */ + if( pCursor->bEOF ){ + return SQLITE_OK; + } + + /* Load the first cell, and iterate forward if it's not valid. If no cells at + * all are valid, recoverNext() sets bEOF and returns appropriately. + */ rc = leafCursorCellDecode(pCursor->pLeafCursor); if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){ return recoverNext(pVtabCursor); diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/src/src/recover.c index 6430c8b..24ccfbd 100644 --- a/third_party/sqlite/src/src/recover.c +++ b/third_party/sqlite/src/src/recover.c @@ -1627,6 +1627,12 @@ static int recoverOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ pCursor->pLeafCursor = pLeafCursor; pCursor->iEncoding = iEncoding; + /* If no leaf pages were found, empty result set. */ + /* TODO(shess): leafCursorNextValidCell() would return SQLITE_ROW or + * SQLITE_DONE to indicate whether there is further data to consider. + */ + pCursor->bEOF = (pLeafCursor->pPage==NULL); + *ppCursor = (sqlite3_vtab_cursor*)pCursor; return SQLITE_OK; } @@ -1715,8 +1721,14 @@ static int recoverFilter( FNENTRY(); - /* Load the first cell, and iterate forward if it's not valid. */ - /* TODO(shess): What happens if no cells at all are valid? */ + /* There were no valid leaf pages in the table. */ + if( pCursor->bEOF ){ + return SQLITE_OK; + } + + /* Load the first cell, and iterate forward if it's not valid. If no cells at + * all are valid, recoverNext() sets bEOF and returns appropriately. + */ rc = leafCursorCellDecode(pCursor->pLeafCursor); if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){ return recoverNext(pVtabCursor); |