Diff
Modified: trunk/LayoutTests/ChangeLog (183645 => 183646)
--- trunk/LayoutTests/ChangeLog 2015-04-30 22:00:47 UTC (rev 183645)
+++ trunk/LayoutTests/ChangeLog 2015-04-30 22:15:29 UTC (rev 183646)
@@ -1,3 +1,14 @@
+2015-04-30 Brady Eidson <beid...@apple.com>
+
+ _javascript_ using WebSQL can create their own WebKit info table.
+ <rdar://problem/20688792> and https://bugs.webkit.org/show_bug.cgi?id=144466
+
+ Reviewed by Alex Christensen.
+
+ * storage/websql/alter-to-info-table-expected.txt: Added.
+ * storage/websql/alter-to-info-table.html: Added.
+ * storage/websql/alter-to-info-table.js: Added.
+
2015-04-30 Martin Robinson <mrobin...@igalia.com>
Unskip isolated words tests on WebKitGTK+
Added: trunk/LayoutTests/storage/websql/alter-to-info-table-expected.txt (0 => 183646)
--- trunk/LayoutTests/storage/websql/alter-to-info-table-expected.txt (rev 0)
+++ trunk/LayoutTests/storage/websql/alter-to-info-table-expected.txt 2015-04-30 22:15:29 UTC (rev 183646)
@@ -0,0 +1,10 @@
+This tests that a tricky way to setup your own info table fails.
+CREATE TABLE statement succeeded.
+CREATE TEMP TABLE statement succeeded.
+INSERT IN TEMP TABLE statement succeeded.
+CREATE TRIGGER statement succeeded.
+ALTER TO INFO TABLE statement succeeded.
+Step 1 transaction succeeded.
+Successfully changed DB version
+Step 2 transaction succeeded.
+
Added: trunk/LayoutTests/storage/websql/alter-to-info-table.html (0 => 183646)
--- trunk/LayoutTests/storage/websql/alter-to-info-table.html (rev 0)
+++ trunk/LayoutTests/storage/websql/alter-to-info-table.html 2015-04-30 22:15:29 UTC (rev 183646)
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body _onload_="setupAndRunTest();">
+This tests that a tricky way to setup your own info table fails.<br>
+<pre id="console">
+FAILURE: test didn't run.
+</pre>
+</body>
+</html>
Added: trunk/LayoutTests/storage/websql/alter-to-info-table.js (0 => 183646)
--- trunk/LayoutTests/storage/websql/alter-to-info-table.js (rev 0)
+++ trunk/LayoutTests/storage/websql/alter-to-info-table.js 2015-04-30 22:15:29 UTC (rev 183646)
@@ -0,0 +1,112 @@
+function terminateTest()
+{
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+function logAndTerminateTest(message, error)
+{
+ log(message + ": " + error.message);
+ terminateTest();
+}
+
+function cleanup(db)
+{
+ db.transaction(function(tx) {
+ tx.executeSql("DROP TABLE IF EXISTS Results;");
+ tx.executeSql("DROP TABLE IF EXISTS TempTable;");
+ tx.executeSql("DROP TRIGGER IF EXISTS TempTrigger;");
+ },
+ function(error) {
+ logAndTerminateTest("Cleanup failed", error);
+ });
+}
+
+function statementSuccessCallback(statementType)
+{
+ log(statementType + " statement succeeded.");
+}
+
+function statementErrorCallback(statementType, error)
+{
+ log(statementType + " statement failed: " + error.message);
+ return false;
+}
+
+function executeStatement(tx, statement, operation)
+{
+ tx.executeSql(statement, [],
+ function(result) {
+ statementSuccessCallback(operation);
+ },
+ function(tx, error) {
+ return statementErrorCallback(operation, error);
+ });
+}
+
+function testCallbacks(tx)
+{
+ executeStatement(tx, "CREATE TABLE Results (Key TEXT, Value TEXT);", "CREATE TABLE");
+
+ // Create a temporary table with the same schema as __WebKitDatabaseInfoTable__ and populate it with a valid version.
+ executeStatement(tx, "CREATE TEMPORARY TABLE TempTable (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL);", "CREATE TEMP TABLE");
+ executeStatement(tx, "INSERT INTO TempTable VALUES ('WebKitDatabaseVersionKey','1.0');", "INSERT IN TEMP TABLE");
+
+ // Set up a trigger to capture changes to the table we just created.
+ executeStatement(tx, "CREATE TRIGGER TempTrigger BEFORE INSERT ON TempTable BEGIN INSERT INTO Results VALUES (NEW.key, NEW.value); END;", "CREATE TRIGGER");
+
+ // Try to spoof that table as the info table.
+ executeStatement(tx, "ALTER TABLE TempTable RENAME TO __WebKitDatabaseInfoTable__;", "ALTER TO INFO TABLE");
+}
+
+function testStep1(db)
+{
+ db.transaction(function(tx) {
+ testCallbacks(tx);
+ },
+ function(error) {
+ logAndTerminateTest("Step 1 transaction failed", error);
+ },
+ function() {
+ log("Step 1 transaction succeeded.");
+ testStep2(db);
+ });
+}
+
+function testStep2(db)
+{
+ // At this point there's a temporary table named the same as the internal info table.
+ // WebKit should not use it.
+ db.changeVersion('1.0', '2.0', null, function(error) {
+ log("Failed to change DB version - " + error.message);
+ },
+ function() {
+ log("Successfully changed DB version");
+ });
+
+ // If our trigger fired it will have captured the changed to the info table and put them in the results table.
+ db.transaction(function(tx) {
+ tx.executeSql("SELECT * FROM Results;", [], function(tx, results) {
+ if (results.rows.length == 0)
+ return;
+ log("The Results table actually has stuff in it, and it shouldn't");
+ var result = results.rows.item(0);
+ for (n in result)
+ log(n + " " + result[n]);
+ });
+ },
+ function(error) {
+ logAndTerminateTest("Step 2 transaction failed", error);
+ },
+ function() {
+ log("Step 2 transaction succeeded.");
+ terminateTest();
+ });
+}
+
+function runTest()
+{
+ var db = openDatabaseWithSuffix("AlterInfoTableTest", "1.0", "Tests altering the info table", 32768);
+ cleanup(db);
+ testStep1(db);
+}
Modified: trunk/LayoutTests/storage/websql/test-authorizer-expected.txt (183645 => 183646)
--- trunk/LayoutTests/storage/websql/test-authorizer-expected.txt 2015-04-30 22:00:47 UTC (rev 183645)
+++ trunk/LayoutTests/storage/websql/test-authorizer-expected.txt 2015-04-30 22:15:29 UTC (rev 183646)
@@ -15,6 +15,9 @@
SQLITE_PRAGMA statement failed: could not prepare statement (23 not authorized)
SQLITE_ALTER_TABLE statement succeeded.
SQLITE_ALTER_TABLE statement succeeded.
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (23 not authorized)
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (23 not authorized)
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (1 there is already another table or index with this name: __WebKitDatabaseInfoTable__)
SQLITE_TRANSACTION statement failed: could not prepare statement (23 not authorized)
SQLITE_ATTACH statement failed: could not prepare statement (23 not authorized)
SQLITE_DETACH statement failed: could not prepare statement (23 not authorized)
@@ -52,6 +55,9 @@
SQLITE_PRAGMA statement failed: could not prepare statement (23 not authorized)
SQLITE_ALTER_TABLE statement failed: could not prepare statement (23 not authorized)
SQLITE_ALTER_TABLE statement failed: could not prepare statement (1 no such table: TestTable)
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (23 not authorized)
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (23 not authorized)
+SQLITE_ALTER_INFO_TABLE statement failed: could not prepare statement (1 there is already another table or index with this name: __WebKitDatabaseInfoTable__)
SQLITE_TRANSACTION statement failed: could not prepare statement (23 not authorized)
SQLITE_ATTACH statement failed: could not prepare statement (23 not authorized)
SQLITE_DETACH statement failed: could not prepare statement (23 not authorized)
Modified: trunk/LayoutTests/storage/websql/test-authorizer.js (183645 => 183646)
--- trunk/LayoutTests/storage/websql/test-authorizer.js 2015-04-30 22:00:47 UTC (rev 183645)
+++ trunk/LayoutTests/storage/websql/test-authorizer.js 2015-04-30 22:15:29 UTC (rev 183646)
@@ -73,6 +73,11 @@
// Rename the table back to its original name
executeStatement(tx, "ALTER TABLE TestTable RENAME To Test;", "SQLITE_ALTER_TABLE");
+ // These should always fail, as nobody gets to mess with the info table.
+ executeStatement(tx, "ALTER TABLE __WebKitDatabaseInfoTable__ RENAME TO TestTable;", "SQLITE_ALTER_INFO_TABLE");
+ executeStatement(tx, "ALTER TABLE main.__WebKitDatabaseInfoTable__ RENAME TO TestTable;", "SQLITE_ALTER_INFO_TABLE");
+ executeStatement(tx, "ALTER TABLE Test RENAME TO __WebKitDatabaseInfoTable__;", "SQLITE_ALTER_INFO_TABLE");
+
executeStatement(tx, "BEGIN TRANSACTION;", "SQLITE_TRANSACTION");
executeStatement(tx, "ATTACH main AS TestMain;", "SQLITE_ATTACH");
executeStatement(tx, "DETACH TestMain;", "SQLITE_DETACH");
Modified: trunk/Source/WebCore/ChangeLog (183645 => 183646)
--- trunk/Source/WebCore/ChangeLog 2015-04-30 22:00:47 UTC (rev 183645)
+++ trunk/Source/WebCore/ChangeLog 2015-04-30 22:15:29 UTC (rev 183646)
@@ -1,3 +1,20 @@
+2015-04-30 Brady Eidson <beid...@apple.com>
+
+ _javascript_ using WebSQL can create their own WebKit info table.
+ <rdar://problem/20688792> and https://bugs.webkit.org/show_bug.cgi?id=144466
+
+ Reviewed by Alex Christensen.
+
+ Test: storage/websql/alter-to-info-table.html
+
+ * Modules/webdatabase/DatabaseBackendBase.cpp:
+ (WebCore::DatabaseBackendBase::databaseInfoTableName): Return the info table name.
+ (WebCore::fullyQualifiedInfoTableName): Append "main." to the info table name.
+ (WebCore::DatabaseBackendBase::DatabaseBackendBase): Use the fully qualified name.
+ (WebCore::DatabaseBackendBase::performOpenAndVerify): Ditto.
+ (WebCore::DatabaseBackendBase::getVersionFromDatabase): Ditto.
+ (WebCore::DatabaseBackendBase::setVersionInDatabase): Ditto.
+
2015-04-30 Beth Dakin <bda...@apple.com>
Should choose UIScrollView indicatorStyle based on the document background color
Modified: trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendBase.cpp (183645 => 183646)
--- trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendBase.cpp 2015-04-30 22:00:47 UTC (rev 183645)
+++ trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendBase.cpp 2015-04-30 22:15:29 UTC (rev 183646)
@@ -82,8 +82,27 @@
namespace WebCore {
static const char versionKey[] = "WebKitDatabaseVersionKey";
-static const char infoTableName[] = "__WebKitDatabaseInfoTable__";
+static const char unqualifiedInfoTableName[] = "__WebKitDatabaseInfoTable__";
+const char* DatabaseBackendBase::databaseInfoTableName()
+{
+ return unqualifiedInfoTableName;
+}
+
+static const char* fullyQualifiedInfoTableName()
+{
+ static const char qualifier[] = "main.";
+ static char qualifiedName[sizeof(qualifier) + sizeof(unqualifiedInfoTableName) - 1];
+
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, []{
+ char* newDestination = stpcpy(qualifiedName, qualifier);
+ strcpy(newDestination, unqualifiedInfoTableName);
+ });
+
+ return qualifiedName;
+}
+
static String formatErrorMessage(const char* message, int sqliteErrorCode, const char* sqliteErrorMessage)
{
return String::format("%s (%d %s)", message, sqliteErrorCode, sqliteErrorMessage);
@@ -190,12 +209,6 @@
return guid;
}
-// static
-const char* DatabaseBackendBase::databaseInfoTableName()
-{
- return infoTableName;
-}
-
#if !LOG_DISABLED || !ERROR_DISABLED
String DatabaseBackendBase::databaseDebugName() const
{
@@ -214,7 +227,7 @@
{
m_contextThreadSecurityOrigin = m_databaseContext->securityOrigin()->isolatedCopy();
- m_databaseAuthorizer = DatabaseAuthorizer::create(infoTableName);
+ m_databaseAuthorizer = DatabaseAuthorizer::create(unqualifiedInfoTableName);
if (m_name.isNull())
m_name = emptyString();
@@ -344,7 +357,7 @@
return false;
}
- String tableName(infoTableName);
+ String tableName(unqualifiedInfoTableName);
if (!m_sqliteDatabase.tableExists(tableName)) {
m_new = true;
@@ -443,7 +456,7 @@
bool DatabaseBackendBase::getVersionFromDatabase(String& version, bool shouldCacheVersion)
{
- String query(String("SELECT value FROM ") + infoTableName + " WHERE key = '" + versionKey + "';");
+ String query(String("SELECT value FROM ") + fullyQualifiedInfoTableName() + " WHERE key = '" + versionKey + "';");
m_databaseAuthorizer->disable();
@@ -463,7 +476,7 @@
{
// The INSERT will replace an existing entry for the database with the new version number, due to the UNIQUE ON CONFLICT REPLACE
// clause in the CREATE statement (see Database::performOpenAndVerify()).
- String query(String("INSERT INTO ") + infoTableName + " (key, value) VALUES ('" + versionKey + "', ?);");
+ String query(String("INSERT INTO ") + fullyQualifiedInfoTableName() + " (key, value) VALUES ('" + versionKey + "', ?);");
m_databaseAuthorizer->disable();