Title: [290822] trunk/Source/WebCore
Revision
290822
Author
sihui_...@apple.com
Date
2022-03-04 00:42:45 -0800 (Fri, 04 Mar 2022)

Log Message

SQLiteDatabase::open should return early if journal mode cannot be set
https://bugs.webkit.org/show_bug.cgi?id=237130
<rdar://83130954>

Reviewed by Darin Adler.

Add early return in SQLiteDatabase::open if key operation fails; also make sure error is properly set and
database is closed in the case.

* platform/sql/SQLiteDatabase.cpp:
(WebCore::SQLiteDatabase::open):
(WebCore::SQLiteDatabase::useWALJournalMode):
(WebCore::SQLiteDatabase::close):
* platform/sql/SQLiteDatabase.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (290821 => 290822)


--- trunk/Source/WebCore/ChangeLog	2022-03-04 08:10:17 UTC (rev 290821)
+++ trunk/Source/WebCore/ChangeLog	2022-03-04 08:42:45 UTC (rev 290822)
@@ -1,3 +1,20 @@
+2022-03-04  Sihui Liu  <sihui_...@apple.com>
+
+        SQLiteDatabase::open should return early if journal mode cannot be set
+        https://bugs.webkit.org/show_bug.cgi?id=237130
+        <rdar://83130954>
+
+        Reviewed by Darin Adler.
+
+        Add early return in SQLiteDatabase::open if key operation fails; also make sure error is properly set and 
+        database is closed in the case.
+
+        * platform/sql/SQLiteDatabase.cpp:
+        (WebCore::SQLiteDatabase::open):
+        (WebCore::SQLiteDatabase::useWALJournalMode):
+        (WebCore::SQLiteDatabase::close):
+        * platform/sql/SQLiteDatabase.h:
+
 2022-03-04  Youenn Fablet  <you...@apple.com>
 
         webrtc/canvas-to-peer-connection.html is flakily failing a test assertion

Modified: trunk/Source/WebCore/platform/sql/SQLiteDatabase.cpp (290821 => 290822)


--- trunk/Source/WebCore/platform/sql/SQLiteDatabase.cpp	2022-03-04 08:10:17 UTC (rev 290821)
+++ trunk/Source/WebCore/platform/sql/SQLiteDatabase.cpp	2022-03-04 08:42:45 UTC (rev 290822)
@@ -38,6 +38,7 @@
 #include <thread>
 #include <wtf/FileSystem.h>
 #include <wtf/Lock.h>
+#include <wtf/Scope.h>
 #include <wtf/Threading.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/StringConcatenateNumbers.h>
@@ -96,9 +97,18 @@
 bool SQLiteDatabase::open(const String& filename, OpenMode openMode)
 {
     initializeSQLiteIfNecessary();
-
     close();
 
+    auto closeDatabase = makeScopeExit([&]() {
+        if (!m_db)
+            return;
+
+        m_openingThread = nullptr;
+        m_openErrorMessage = sqlite3_errmsg(m_db);
+        m_openError = sqlite3_errcode(m_db);
+        close();
+    });
+
     {
         Locker locker { isDatabaseOpeningForbiddenLock };
         if (isDatabaseOpeningForbidden) {
@@ -119,15 +129,17 @@
             break;
         }
 
+        int result = SQLITE_OK;
         {
             SQLiteTransactionInProgressAutoCounter transactionCounter;
-            m_openError = sqlite3_open_v2(FileSystem::fileSystemRepresentation(filename).data(), &m_db, flags, nullptr);
+            result = sqlite3_open_v2(FileSystem::fileSystemRepresentation(filename).data(), &m_db, flags, nullptr);
         }
-        if (m_openError != SQLITE_OK) {
-            m_openErrorMessage = m_db ? sqlite3_errmsg(m_db) : "sqlite_open returned null";
-            LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
-                m_openErrorMessage.data());
-            close(ShouldSetErrorState::No);
+
+        if (result != SQLITE_OK) {
+            if (!m_db) {
+                m_openError = result;
+                m_openErrorMessage = "sqlite_open returned null";
+            }
             return false;
         }
     }
@@ -134,19 +146,10 @@
 
     overrideUnauthorizedFunctions();
 
-    m_openError = sqlite3_extended_result_codes(m_db, 1);
-    if (m_openError != SQLITE_OK) {
-        m_openErrorMessage = sqlite3_errmsg(m_db);
-        LOG_ERROR("SQLite database error when enabling extended errors - %s", m_openErrorMessage.data());
-        close(ShouldSetErrorState::No);
+    m_openingThread = &Thread::current();
+    if (sqlite3_extended_result_codes(m_db, 1) != SQLITE_OK)
         return false;
-    }
 
-    if (isOpen())
-        m_openingThread = &Thread::current();
-    else
-        m_openErrorMessage = "sqlite_open returned null";
-
     {
         SQLiteTransactionInProgressAutoCounter transactionCounter;
         if (!executeCommand("PRAGMA temp_store = MEMORY;"_s))
@@ -154,19 +157,18 @@
     }
 
     if (filename != inMemoryPath()) {
-        if (openMode != OpenMode::ReadOnly)
-            useWALJournalMode();
+        if (openMode != OpenMode::ReadOnly && !useWALJournalMode())
+            return false;
 
         auto shmFileName = makeString(filename, "-shm"_s);
-        if (FileSystem::fileExists(shmFileName)) {
-            if (!FileSystem::isSafeToUseMemoryMapForPath(shmFileName)) {
-                RELEASE_LOG_FAULT(SQLDatabase, "Opened an SQLite database with a Class A -shm file. This may trigger a crash when the user locks the device. (%s)", shmFileName.latin1().data());
-                FileSystem::makeSafeToUseMemoryMapForPath(shmFileName);
-            }
+        if (FileSystem::fileExists(shmFileName) && !FileSystem::isSafeToUseMemoryMapForPath(shmFileName)) {
+            RELEASE_LOG_FAULT(SQLDatabase, "Opened an SQLite database with a Class A -shm file. This may trigger a crash when the user locks the device. (%s)", shmFileName.latin1().data());
+            FileSystem::makeSafeToUseMemoryMapForPath(shmFileName);
         }
     }
 
-    return isOpen();
+    closeDatabase.release();
+    return true;
 }
 
 static int walAutomaticTruncationHook(void* context, sqlite3* db, const char* dbName, int walPageCount)
@@ -228,26 +230,35 @@
     LOG_ERROR("SQLite database failed to checkpoint: %s", lastErrorMsg());
 }
 
-void SQLiteDatabase::useWALJournalMode()
+bool SQLiteDatabase::useWALJournalMode()
 {
     m_useWAL = true;
     {
         SQLiteTransactionInProgressAutoCounter transactionCounter;
         auto walStatement = prepareStatement("PRAGMA journal_mode=WAL;"_s);
-        if (walStatement && walStatement->step() == SQLITE_ROW) {
+        if (!walStatement)
+            return false;
+
+        int stepResult = walStatement->step();
+        if (stepResult != SQLITE_ROW)
+            return false;
+
 #ifndef NDEBUG
-            String mode = walStatement->columnText(0);
-            if (!equalLettersIgnoringASCIICase(mode, "wal"))
-                LOG_ERROR("journal_mode of database should be 'WAL', but is '%s'", mode.utf8().data());
+        String mode = walStatement->columnText(0);
+        if (!equalLettersIgnoringASCIICase(mode, "wal")) {
+            LOG_ERROR("SQLite database journal_mode should be 'WAL', but is '%s'", mode.utf8().data());
+            return false;
+        }
 #endif
-        } else
-            LOG_ERROR("SQLite database failed to set journal_mode to WAL, error: %s", lastErrorMsg());
     }
 
+    // The database can be used even if checkpoint fails, e.g. when there are multiple open database connections.
     checkpoint(CheckpointMode::Truncate);
+
+    return true;
 }
 
-void SQLiteDatabase::close(ShouldSetErrorState shouldSetErrorState)
+void SQLiteDatabase::close()
 {
     if (m_db) {
         ASSERT_WITH_MESSAGE(!m_statementCount, "All SQLiteTransaction objects should be destroyed before closing the database");
@@ -271,12 +282,6 @@
         if (closeResult != SQLITE_OK)
             RELEASE_LOG_ERROR(SQLDatabase, "SQLiteDatabase::close: Failed to close database (%d) - %" PUBLIC_LOG_STRING, closeResult, lastErrorMsg());
     }
-
-    if (shouldSetErrorState == ShouldSetErrorState::Yes) {
-        m_openingThread = nullptr;
-        m_openError = SQLITE_ERROR;
-        m_openErrorMessage = CString();
-    }
 }
 
 void SQLiteDatabase::overrideUnauthorizedFunctions()

Modified: trunk/Source/WebCore/platform/sql/SQLiteDatabase.h (290821 => 290822)


--- trunk/Source/WebCore/platform/sql/SQLiteDatabase.h	2022-03-04 08:10:17 UTC (rev 290821)
+++ trunk/Source/WebCore/platform/sql/SQLiteDatabase.h	2022-03-04 08:42:45 UTC (rev 290822)
@@ -61,8 +61,7 @@
     enum class OpenMode { ReadOnly, ReadWrite, ReadWriteCreate };
     WEBCORE_EXPORT bool open(const String& filename, OpenMode = OpenMode::ReadWriteCreate);
     bool isOpen() const { return m_db; }
-    enum class ShouldSetErrorState : bool { No, Yes };
-    WEBCORE_EXPORT void close(ShouldSetErrorState = ShouldSetErrorState::Yes);
+    WEBCORE_EXPORT void close();
 
     WEBCORE_EXPORT bool executeCommandSlow(const String&);
     WEBCORE_EXPORT bool executeCommand(ASCIILiteral);
@@ -170,7 +169,7 @@
     static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*);
 
     void enableAuthorizer(bool enable) WTF_REQUIRES_LOCK(m_authorizerLock);
-    void useWALJournalMode();
+    bool useWALJournalMode();
 
     int pageSize();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to