From 8b5f7c745c245317412fa7bb0892607fb07f1e6f Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Sat, 13 Jan 2024 15:52:08 +0100
Subject: [PATCH] OGR2SQLITE_Setup(): robustify against potential crashing
 scenario

---
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp |  7 +++++++
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp | 11 +++++++++++
 2 files changed, 18 insertions(+)

diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
index 940ec56f2351..79d3340d95ba 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
@@ -946,6 +946,13 @@ OGRLayer *OGRSQLiteExecuteSQL(GDALDataset *poDS, const char *pszStatement,
     /*      Attach the Virtual Table OGR2SQLITE module to it.               */
     /* -------------------------------------------------------------------- */
     OGR2SQLITEModule *poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS);
+    if (!poModule)
+    {
+        delete poSQLiteDS;
+        VSIUnlink(pszTmpDBName);
+        CPLFree(pszTmpDBName);
+        return nullptr;
+    }
     sqlite3 *hDB = poSQLiteDS->GetDB();
 
     /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
index 250a9aedda9b..ef598f460023 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
@@ -2721,6 +2721,17 @@ int OGR2SQLITEModule::Setup(sqlite3 *hDBIn)
 OGR2SQLITEModule *OGR2SQLITE_Setup(GDALDataset *poDS,
                                    OGRSQLiteDataSource *poSQLiteDS)
 {
+    if (sqlite3_api == nullptr)
+    {
+        // Unlikely to happen. One theoretical possibility would be that:
+        // - thread A calls OGR2SQLITE_Register(), which calls sqlite3_auto_extension((void (*)(void))OGR2SQLITE_static_register)
+        // - thread B calls sqlite3_reset_auto_extension()
+        // - thread A opens a sqlite3 handle (which normally would have caused OGR2SQLITE_static_register() to be called, and setting the sqlite3_api static variable, without prior B intervention.
+        // - thread A calls us (OGR2SQLITE_Setup()) with sqlite3_api still set to its initial nullptr value
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "OGR2SQLITE_Setup() failed due to sqlite3_api == nullptr");
+        return nullptr;
+    }
     OGR2SQLITEModule *poModule = new OGR2SQLITEModule();
     poModule->Setup(poDS, poSQLiteDS);
     return poModule;