Skip to content

Commit 8ed21a8

Browse files
committed
Fix phpGH-9032: SQLite3 authorizer crashes on NULL values
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 phpGH-9040.
1 parent a442e29 commit 8ed21a8

File tree

5 files changed

+68
-2
lines changed

5 files changed

+68
-2
lines changed

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ PHP NEWS
1111
. Fixed bug GH-9033 (Loading blacklist file can fail due to negative length).
1212
(cmb)
1313

14+
- PDO_SQLite:
15+
. Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb)
16+
17+
- SQLite3:
18+
. Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb)
19+
1420
- Standard:
1521
. Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL).
1622
(Heiko Weber)

ext/pdo_sqlite/sqlite_driver.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,9 @@ static const struct pdo_dbh_methods sqlite_methods = {
715715

716716
static char *make_filename_safe(const char *filename)
717717
{
718+
if (!filename) {
719+
return NULL;
720+
}
718721
if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
719722
char *fullpath = expand_filepath(filename, NULL);
720723

@@ -737,7 +740,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
737740
char *filename;
738741
switch (access_type) {
739742
case SQLITE_COPY: {
740-
filename = make_filename_safe(arg4);
743+
filename = make_filename_safe(arg4);
741744
if (!filename) {
742745
return SQLITE_DENY;
743746
}
@@ -746,7 +749,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
746749
}
747750

748751
case SQLITE_ATTACH: {
749-
filename = make_filename_safe(arg3);
752+
filename = make_filename_safe(arg3);
750753
if (!filename) {
751754
return SQLITE_DENY;
752755
}

ext/pdo_sqlite/tests/gh9032.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
SQLite3 authorizer crashes on NULL values
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("pdo_sqlite")) die("skip pdo_sqlite extension not available");
6+
?>
7+
--INI--
8+
open_basedir=.
9+
--FILE--
10+
<?php
11+
$db = new PDO("sqlite::memory:", null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
12+
13+
$db->exec('attach database \':memory:\' AS "db1"');
14+
var_dump($db->exec('create table db1.r (id int)'));
15+
16+
try {
17+
$st = $db->prepare('attach database :a AS "db2"');
18+
$st->execute([':a' => ':memory:']);
19+
var_dump($db->exec('create table db2.r (id int)'));
20+
} catch (PDOException $ex) {
21+
echo $ex->getMessage(), PHP_EOL;
22+
}
23+
?>
24+
--EXPECT--
25+
int(0)
26+
SQLSTATE[HY000]: General error: 23 not authorized

ext/sqlite3/sqlite3.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,6 +2049,9 @@ static int php_sqlite3_authorizer(void *autharg, int action, const char *arg1, c
20492049
/* Check open_basedir restrictions first */
20502050
if (PG(open_basedir) && *PG(open_basedir)) {
20512051
if (action == SQLITE_ATTACH) {
2052+
if (!arg1) {
2053+
return SQLITE_DENY;
2054+
}
20522055
if (memcmp(arg1, ":memory:", sizeof(":memory:")) && *arg1) {
20532056
if (strncmp(arg1, "file:", 5) == 0) {
20542057
/* starts with "file:" */

ext/sqlite3/tests/gh9032.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
SQLite3 authorizer crashes on NULL values
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("sqlite3")) die("skip sqlite3 extension not available");
6+
?>
7+
--INI--
8+
open_basedir=.
9+
--FILE--
10+
<?php
11+
$db = new SQLite3(":memory:");
12+
$db->enableExceptions(true);
13+
14+
$db->exec('attach database \':memory:\' AS "db1"');
15+
var_dump($db->exec('create table db1.r (id int)'));
16+
17+
try {
18+
$st = $db->prepare('attach database :a AS "db2"');
19+
$st->bindValue("a", ":memory:");
20+
$st->execute();
21+
var_dump($db->exec('create table db2.r (id int)'));
22+
} catch (Exception $ex) {
23+
echo $ex->getMessage(), PHP_EOL;
24+
}
25+
?>
26+
--EXPECT--
27+
bool(true)
28+
Unable to prepare statement: 23, not authorized

0 commit comments

Comments
 (0)