]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix loading SQLite extensions
authorEli Zaretskii <eliz@gnu.org>
Sat, 20 May 2023 12:43:44 +0000 (15:43 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 20 May 2023 12:43:44 +0000 (15:43 +0300)
* src/sqlite.c (sqlite3_db_config) [WINDOWSNT]: Load from the DLL.
(Fsqlite_load_extension): Use 'sqlite3_db_config' to enable and
disable loading of extensions.  Add a few free extensions to the
allow-list.  Fix testing for the ".dll" extension.  (Bug#63590)

* test/src/sqlite-tests.el (sqlite-load-extension): Fix the test
to require successful load if the extension does exist.

src/sqlite.c
test/src/sqlite-tests.el

index 0361514766a4fd3b5de4483f7daffc5754805977..77ce61ba6578f9fa3f3eef02f5d18dbf9b2e7875 100644 (file)
@@ -23,6 +23,8 @@ YOSHIDA <syohex@gmail.com>, which can be found at:
    https://github.com/syohex/emacs-sqlite3  */
 
 #include <config.h>
+
+#include <c-strcase.h>
 #include "lisp.h"
 #include "coding.h"
 
@@ -80,6 +82,9 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
            (sqlite3*, const char*, const char*, char**));
 #  undef sqlite3_load_extension
 #  define sqlite3_load_extension fn_sqlite3_load_extension
+DEF_DLL_FN (SQLITE_API int, sqlite3_db_config, (sqlite3*, int, ...));
+#  undef sqlite3_db_config
+#  define sqlite3_db_config fn_sqlite3_db_config
 # endif
 
 # undef sqlite3_finalize
@@ -172,6 +177,7 @@ load_dll_functions (HMODULE library)
   LOAD_DLL_FN (library, sqlite3_exec);
 # ifdef HAVE_SQLITE3_LOAD_EXTENSION
   LOAD_DLL_FN (library, sqlite3_load_extension);
+  LOAD_DLL_FN (library, sqlite3_db_config);
 # endif
   LOAD_DLL_FN (library, sqlite3_prepare_v2);
   return true;
@@ -684,9 +690,28 @@ Only modules on Emacs' list of allowed modules can be loaded.  */)
   CHECK_STRING (module);
 
   /* Add names of useful and free modules here.  */
-  const char *allowlist[3] = { "pcre", "csvtable", NULL };
+  const char *allowlist[] = {
+    "base64",
+    "cksumvfs",
+    "compress",
+    "csv",
+    "csvtable",
+    "fts3",
+    "icu",
+    "pcre",
+    "percentile",
+    "regexp",
+    "rot13",
+    "rtree",
+    "sha1",
+    "uuid",
+    "vfslog",
+    "zipfile",
+    NULL
+  };
   char *name = SSDATA (Ffile_name_nondirectory (module));
-  /* Possibly skip past a common prefix.  */
+  /* Possibly skip past a common prefix (libsqlite3_mod_ is used by
+     Debian, see https://packages.debian.org/source/sid/sqliteodbc).  */
   const char *prefix = "libsqlite3_mod_";
   if (!strncmp (name, prefix, strlen (prefix)))
     name += strlen (prefix);
@@ -697,7 +722,7 @@ Only modules on Emacs' list of allowed modules can be loaded.  */)
       if (strlen (*allow) < strlen (name)
          && !strncmp (*allow, name, strlen (*allow))
          && (!strcmp (name + strlen (*allow), ".so")
-             || !strcmp (name + strlen (*allow), ".DLL")))
+             || !strcasecmp (name + strlen (*allow), ".dll")))
        {
          do_allow = true;
          break;
@@ -707,12 +732,22 @@ Only modules on Emacs' list of allowed modules can be loaded.  */)
   if (!do_allow)
     xsignal1 (Qsqlite_error, build_string ("Module name not on allowlist"));
 
-  int result = sqlite3_load_extension
-                      (XSQLITE (db)->db,
-                       SSDATA (ENCODE_FILE (Fexpand_file_name (module, Qnil))),
-                       NULL, NULL);
-  if (result ==  SQLITE_OK)
-    return Qt;
+  /* Expand all Lisp data explicitly, so as to avoid signaling an
+     error while extension loading is enabled -- we don't want to
+     "leak" this outside this function.  */
+  sqlite3 *sdb = XSQLITE (db)->db;
+  char *ext_fn = SSDATA (ENCODE_FILE (Fexpand_file_name (module, Qnil)));
+  /* Temporarily enable loading extensions via the C API.  */
+  int result = sqlite3_db_config (sdb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1,
+                                 NULL);
+  if (result == SQLITE_OK)
+    {
+      result = sqlite3_load_extension (sdb, ext_fn, NULL, NULL);
+      /* Disable loading extensions via C API.  */
+      sqlite3_db_config (sdb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0, NULL);
+      if (result == SQLITE_OK)
+       return Qt;
+    }
   return Qnil;
 }
 #endif /* HAVE_SQLITE3_LOAD_EXTENSION */
index 460651def781c054fa021c1a9ccfa0cb68120102..f7144c158875fc88d6f64aa92781f442aca0f47e 100644 (file)
      (sqlite-load-extension db "/usr/lib/sqlite3/"))
     (should-error
      (sqlite-load-extension db "/usr/lib/sqlite3"))
-    (should
-     (memq
-      (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
-      '(nil t)))
+    (if (eq system-type 'windows-nt)
+        (should
+         (eq (sqlite-load-extension db "/usr/lib/sqlite3/pcre.dll")
+             (file-readable-p "/usr/lib/sqlite3/pcre.dll")))
+      (should
+       (eq (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
+           (file-readable-p "/usr/lib/sqlite3/pcre.so"))))
 
     (should-error
      (sqlite-load-extension
     (should-error
      (sqlite-load-extension
       db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
-    (should
-     (memq
-      (sqlite-load-extension
-       db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
-      '(nil t)))))
+    (if (eq system-type 'windows-nt)
+        (should
+         (eq (sqlite-load-extension db "/usr/lib/sqlite3/csvtable.dll")
+             (file-readable-p "/usr/lib/sqlite3/csvtable.dll")))
+      (should
+       (eq (sqlite-load-extension db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
+           (file-readable-p "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so"))))))
 
 (ert-deftest sqlite-blob ()
   (skip-unless (sqlite-available-p))