mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fix GH-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 GH-9040.
This commit is contained in:
parent
a442e29485
commit
8ed21a89f3
5 changed files with 68 additions and 2 deletions
6
NEWS
6
NEWS
|
@ -11,6 +11,12 @@ PHP NEWS
|
||||||
. Fixed bug GH-9033 (Loading blacklist file can fail due to negative length).
|
. Fixed bug GH-9033 (Loading blacklist file can fail due to negative length).
|
||||||
(cmb)
|
(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:
|
- Standard:
|
||||||
. Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL).
|
. Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL).
|
||||||
(Heiko Weber)
|
(Heiko Weber)
|
||||||
|
|
|
@ -715,6 +715,9 @@ static const struct pdo_dbh_methods sqlite_methods = {
|
||||||
|
|
||||||
static char *make_filename_safe(const char *filename)
|
static char *make_filename_safe(const char *filename)
|
||||||
{
|
{
|
||||||
|
if (!filename) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
|
if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
|
||||||
char *fullpath = expand_filepath(filename, NULL);
|
char *fullpath = expand_filepath(filename, NULL);
|
||||||
|
|
||||||
|
@ -737,7 +740,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
|
||||||
char *filename;
|
char *filename;
|
||||||
switch (access_type) {
|
switch (access_type) {
|
||||||
case SQLITE_COPY: {
|
case SQLITE_COPY: {
|
||||||
filename = make_filename_safe(arg4);
|
filename = make_filename_safe(arg4);
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
return SQLITE_DENY;
|
return SQLITE_DENY;
|
||||||
}
|
}
|
||||||
|
@ -746,7 +749,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLITE_ATTACH: {
|
case SQLITE_ATTACH: {
|
||||||
filename = make_filename_safe(arg3);
|
filename = make_filename_safe(arg3);
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
return SQLITE_DENY;
|
return SQLITE_DENY;
|
||||||
}
|
}
|
||||||
|
|
26
ext/pdo_sqlite/tests/gh9032.phpt
Normal file
26
ext/pdo_sqlite/tests/gh9032.phpt
Normal file
|
@ -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
|
|
@ -2049,6 +2049,9 @@ static int php_sqlite3_authorizer(void *autharg, int action, const char *arg1, c
|
||||||
/* Check open_basedir restrictions first */
|
/* Check open_basedir restrictions first */
|
||||||
if (PG(open_basedir) && *PG(open_basedir)) {
|
if (PG(open_basedir) && *PG(open_basedir)) {
|
||||||
if (action == SQLITE_ATTACH) {
|
if (action == SQLITE_ATTACH) {
|
||||||
|
if (!arg1) {
|
||||||
|
return SQLITE_DENY;
|
||||||
|
}
|
||||||
if (memcmp(arg1, ":memory:", sizeof(":memory:")) && *arg1) {
|
if (memcmp(arg1, ":memory:", sizeof(":memory:")) && *arg1) {
|
||||||
if (strncmp(arg1, "file:", 5) == 0) {
|
if (strncmp(arg1, "file:", 5) == 0) {
|
||||||
/* starts with "file:" */
|
/* starts with "file:" */
|
||||||
|
|
28
ext/sqlite3/tests/gh9032.phpt
Normal file
28
ext/sqlite3/tests/gh9032.phpt
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue