Skip to content

Commit

Permalink
Fix GH-9032: SQLite3 authorizer crashes on NULL values
Browse files Browse the repository at this point in the history
The arguments 3 to 6 of the authorizer callback may be `NULL`[1], and
we have to properly deal with that.  Instead of causing a segfault, we
deny authorization, which is still better than a crash, and apparently,
we cannot do better anyway.

[1] <https://www.sqlite.org/c3ref/set_authorizer.html>

Closes GH-9040.
  • Loading branch information
cmb69 committed Jul 27, 2022
1 parent a442e29 commit 8ed21a8
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
6 changes: 6 additions & 0 deletions NEWS
Expand Up @@ -11,6 +11,12 @@ PHP NEWS
. Fixed bug GH-9033 (Loading blacklist file can fail due to negative length).
(cmb)

- PDO_SQLite:
. Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb)

- SQLite3:
. Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb)

- Standard:
. Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL).
(Heiko Weber)
Expand Down
7 changes: 5 additions & 2 deletions ext/pdo_sqlite/sqlite_driver.c
Expand Up @@ -715,6 +715,9 @@ static const struct pdo_dbh_methods sqlite_methods = {

static char *make_filename_safe(const char *filename)
{
if (!filename) {
return NULL;
}
if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
char *fullpath = expand_filepath(filename, NULL);

Expand All @@ -737,7 +740,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
char *filename;
switch (access_type) {
case SQLITE_COPY: {
filename = make_filename_safe(arg4);
filename = make_filename_safe(arg4);
if (!filename) {
return SQLITE_DENY;
}
Expand All @@ -746,7 +749,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
}

case SQLITE_ATTACH: {
filename = make_filename_safe(arg3);
filename = make_filename_safe(arg3);
if (!filename) {
return SQLITE_DENY;
}
Expand Down
26 changes: 26 additions & 0 deletions ext/pdo_sqlite/tests/gh9032.phpt
@@ -0,0 +1,26 @@
--TEST--
SQLite3 authorizer crashes on NULL values
--SKIPIF--
<?php
if (!extension_loaded("pdo_sqlite")) die("skip pdo_sqlite extension not available");
?>
--INI--
open_basedir=.
--FILE--
<?php
$db = new PDO("sqlite::memory:", null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

$db->exec('attach database \':memory:\' AS "db1"');
var_dump($db->exec('create table db1.r (id int)'));

try {
$st = $db->prepare('attach database :a AS "db2"');
$st->execute([':a' => ':memory:']);
var_dump($db->exec('create table db2.r (id int)'));
} catch (PDOException $ex) {
echo $ex->getMessage(), PHP_EOL;
}
?>
--EXPECT--
int(0)
SQLSTATE[HY000]: General error: 23 not authorized
3 changes: 3 additions & 0 deletions ext/sqlite3/sqlite3.c
Expand Up @@ -2049,6 +2049,9 @@ static int php_sqlite3_authorizer(void *autharg, int action, const char *arg1, c
/* Check open_basedir restrictions first */
if (PG(open_basedir) && *PG(open_basedir)) {
if (action == SQLITE_ATTACH) {
if (!arg1) {
return SQLITE_DENY;
}
if (memcmp(arg1, ":memory:", sizeof(":memory:")) && *arg1) {
if (strncmp(arg1, "file:", 5) == 0) {
/* starts with "file:" */
Expand Down
28 changes: 28 additions & 0 deletions ext/sqlite3/tests/gh9032.phpt
@@ -0,0 +1,28 @@
--TEST--
SQLite3 authorizer crashes on NULL values
--SKIPIF--
<?php
if (!extension_loaded("sqlite3")) die("skip sqlite3 extension not available");
?>
--INI--
open_basedir=.
--FILE--
<?php
$db = new SQLite3(":memory:");
$db->enableExceptions(true);

$db->exec('attach database \':memory:\' AS "db1"');
var_dump($db->exec('create table db1.r (id int)'));

try {
$st = $db->prepare('attach database :a AS "db2"');
$st->bindValue("a", ":memory:");
$st->execute();
var_dump($db->exec('create table db2.r (id int)'));
} catch (Exception $ex) {
echo $ex->getMessage(), PHP_EOL;
}
?>
--EXPECT--
bool(true)
Unable to prepare statement: 23, not authorized

0 comments on commit 8ed21a8

Please sign in to comment.