From ead3a2abbfc347b0f562c1e051b370a0617ee8aa Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 20 May 2023 15:43:44 +0300 Subject: [PATCH] Fix loading SQLite extensions * 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 | 53 +++++++++++++++++++++++++++++++++------- test/src/sqlite-tests.el | 23 ++++++++++------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/sqlite.c b/src/sqlite.c index 0361514766a..77ce61ba657 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -23,6 +23,8 @@ YOSHIDA , which can be found at: https://github.com/syohex/emacs-sqlite3 */ #include + +#include #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 */ diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el index 460651def78..f7144c15887 100644 --- a/test/src/sqlite-tests.el +++ b/test/src/sqlite-tests.el @@ -197,10 +197,13 @@ (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 @@ -211,11 +214,13 @@ (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)) -- 2.39.2