Bug 705509 - Crash in mozilla::places::Database::GetAsyncStatement.

r=dietrich
This commit is contained in:
Marco Bonardo 2011-11-29 14:13:09 +01:00
parent c77ee84007
commit 0aa4a85c3a
9 changed files with 146 additions and 7 deletions

View File

@ -597,6 +597,12 @@ Database::InitSchema(bool* aDatabaseMigrated)
if (currentSchemaVersion < DATABASE_SCHEMA_VERSION) {
*aDatabaseMigrated = true;
if (currentSchemaVersion < 6) {
// These are early Firefox 3.0 alpha versions that are not supported
// anymore. In this case it's safer to just replace the database.
return NS_ERROR_FILE_CORRUPTED;
}
// Firefox 3.0 uses schema version 6.
if (currentSchemaVersion < 7) {
@ -929,12 +935,24 @@ nsresult
Database::MigrateV7Up()
{
MOZ_ASSERT(NS_IsMainThread());
// Some old v6 databases come from alpha versions that missed indices.
// Just bail out and replace the database in such a case.
bool URLUniqueIndexExists = false;
nsresult rv = mMainConn->IndexExists(NS_LITERAL_CSTRING(
"moz_places_url_uniqueindex"
), &URLUniqueIndexExists);
NS_ENSURE_SUCCESS(rv, rv);
if (!URLUniqueIndexExists) {
return NS_ERROR_FILE_CORRUPTED;
}
mozStorageTransaction transaction(mMainConn, false);
// We need an index on lastModified to catch quickly last modified bookmark
// title for tag container's children. This will be useful for sync too.
bool lastModIndexExists = false;
nsresult rv = mMainConn->IndexExists(
rv = mMainConn->IndexExists(
NS_LITERAL_CSTRING("moz_bookmarks_itemlastmodifiedindex"),
&lastModIndexExists);
NS_ENSURE_SUCCESS(rv, rv);
@ -982,10 +1000,18 @@ Database::MigrateV7Up()
NS_ENSURE_SUCCESS(rv, rv);
// Invalidate all frecencies, since they need recalculation.
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
rv = history->invalidateFrecencies(EmptyCString());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageAsyncStatement> stmt = GetAsyncStatement(
"UPDATE moz_places SET frecency = ( "
"CASE "
"WHEN url BETWEEN 'place:' AND 'place;' "
"THEN 0 "
"ELSE -1 "
"END "
") "
);
NS_ENSURE_STATE(stmt);
nsCOMPtr<mozIStoragePendingStatement> ps;
(void)stmt->ExecuteAsync(nsnull, getter_AddRefs(ps));
}
// Temporary migration code for bug 396300
@ -1095,6 +1121,16 @@ Database::MigrateV7Up()
NS_ENSURE_SUCCESS(rv, rv);
}
// Add the moz_inputhistory table, if missing.
bool tableExists = false;
rv = mMainConn->TableExists(NS_LITERAL_CSTRING("moz_inputhistory"),
&tableExists);
NS_ENSURE_SUCCESS(rv, rv);
if (!tableExists) {
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_INPUTHISTORY);
NS_ENSURE_SUCCESS(rv, rv);
}
return transaction.Commit();
}
@ -1121,7 +1157,9 @@ Database::MigrateV8Up()
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX IF EXISTS moz_annos_item_idindex"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX IF EXISTS moz_annos_place_idindex"));
NS_ENSURE_SUCCESS(rv, rv);
// Do a one-time re-creation of the moz_annos indexes (bug 415201)
bool oldIndexExists = false;

View File

@ -36,5 +36,5 @@ function setPlacesDatabase(aFileName)
do_check_false(dbFile.exists());
}
file.copyTo(gProfD, kDBName);
file.copyToFollowingLinks(gProfD, kDBName);
}

View File

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests migration replaces the database if schema version < 6.
*/
add_test(function corrupt_database_not_exists() {
let dbFile = gProfD.clone();
dbFile.append("places.sqlite.corrupt");
do_check_false(dbFile.exists());
run_next_test();
});
add_test(function database_is_valid() {
do_check_eq(PlacesUtils.history.databaseStatus,
PlacesUtils.history.DATABASE_STATUS_CORRUPT);
do_check_eq(DBConn().schemaVersion, CURRENT_SCHEMA_VERSION);
run_next_test();
});
add_test(function corrupt_database_exists() {
let dbFile = gProfD.clone();
dbFile.append("places.sqlite.corrupt");
do_check_true(dbFile.exists());
run_next_test();
});
function run_test()
{
setPlacesDatabase("places_alpha.sqlite");
run_next_test();
}

View File

@ -0,0 +1,30 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests migration from a preliminary schema version 6 that
* lacks frecency column and moz_inputhistory table.
*/
add_test(function database_is_valid() {
do_check_eq(PlacesUtils.history.databaseStatus,
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
// This throws if frecency column does not exist.
DBConn().createStatement("SELECT frecency from moz_places");
// Check moz_inputhistory is in place.
do_check_true(DBConn().tableExists("moz_inputhistory"));
run_next_test();
});
add_test(function corrupt_database_not_exists() {
let dbFile = gProfD.clone();
dbFile.append("places.sqlite.corrupt");
do_check_false(dbFile.exists());
run_next_test();
});
function run_test()
{
setPlacesDatabase("places_v6_no_frecency.sqlite");
run_next_test();
}

View File

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests migration from a preliminary schema version 6 that
* lacks important indices. The database should be replaced.
*/
add_test(function corrupt_database_not_exists() {
let dbFile = gProfD.clone();
dbFile.append("places.sqlite.corrupt");
do_check_false(dbFile.exists());
run_next_test();
});
add_test(function database_is_valid() {
do_check_eq(PlacesUtils.history.databaseStatus,
PlacesUtils.history.DATABASE_STATUS_CORRUPT);
do_check_eq(DBConn().schemaVersion, CURRENT_SCHEMA_VERSION);
run_next_test();
});
add_test(function corrupt_database_exists() {
let dbFile = gProfD.clone();
dbFile.append("places.sqlite.corrupt");
do_check_true(dbFile.exists());
run_next_test();
});
function run_test()
{
setPlacesDatabase("places_v6_no_indices.sqlite");
run_next_test();
}

View File

@ -4,3 +4,6 @@ tail =
[test_current_from_v10.js]
[test_current_from_v10_migrated_from_v11.js]
[test_database_from_alpha.js]
[test_database_from_v6_no_frecency.js]
[test_database_from_v6_no_indices.js]