Function: sqlite-load-extension

sqlite-load-extension is a function defined in sqlite.c.

Signature

(sqlite-load-extension DB MODULE)

Documentation

Load an SQlite MODULE into DB.

MODULE should be the name of an SQlite module's file, a shared library in the system-dependent format and having a system-dependent file-name extension.

Only modules on Emacs' list of allowed modules can be loaded.

View in manual

Source Code

// Defined in /usr/src/emacs/src/sqlite.c
{
  check_sqlite (db, false);
  CHECK_STRING (module);

  /* Add names of useful and free modules here.  */
  const char *allowlist[] = {
    "base64",
    "cksumvfs",
    "compress",
    "csv",
    "csvtable",
    "fts3",
    "icu",
    "pcre",
    "percentile",
    "regexp",
    "rot13",
    "rtree",
    "sha1",
    "uuid",
    "vector0",
    "vfslog",
    "vss0",
    "zipfile",
    NULL
  };
  char *name = SSDATA (Ffile_name_nondirectory (module));
  /* 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);

  bool do_allow = false;
  for (const char **allow = allowlist; *allow; allow++)
    {
      ptrdiff_t allow_len = strlen (*allow);
      if (allow_len < strlen (name)
	  && !strncmp (*allow, name, allow_len)
	  && (!strcmp (name + allow_len, ".so")
	      ||!strcmp (name + allow_len, ".dylib")
	      || !strcasecmp (name + allow_len, ".dll")))
	{
	  do_allow = true;
	  break;
	}
    }

  if (!do_allow)
    xsignal1 (Qsqlite_error, build_string ("Module name not on allowlist"));

  /* 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;
}