From df3ad4749364108c33416d3b4cc5a9db0e0e9276 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 18 Feb 2025 16:44:14 +0100 Subject: [PATCH] Fix GH-17746: Signed integer overflow when setting ATTR_TIMEOUT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `::setAttribute(PDO::ATTR_TIMEOUT, …)` accepts a timeout in seconds, but `sqlite3_busy_timeout()`[1] expects the timeout in milliseconds, which is an `int`. To avoid signed overflow, we reject values larger than the allowed range. We also cater to negative values by simply clamping those to zero, since `sqlite3_busy_timeout()` handles negative values the same as zero. [1] --- ext/pdo_sqlite/sqlite_driver.c | 4 ++++ ext/pdo_sqlite/tests/gh17746.phpt | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 ext/pdo_sqlite/tests/gh17746.phpt diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index c933c34ed1dcd..48b0115413989 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -292,6 +292,10 @@ static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) if (!pdo_get_long_param(&lval, val)) { return false; } + if (lval > INT_MAX / 1000) { + return false; + } + lval = MAX(lval, 0); sqlite3_busy_timeout(H->db, lval * 1000); return true; case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES: diff --git a/ext/pdo_sqlite/tests/gh17746.phpt b/ext/pdo_sqlite/tests/gh17746.phpt new file mode 100644 index 0000000000000..3ece7a73a5ea2 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh17746.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17746 (Signed integer overflow when setting ATTR_TIMEOUT) +--EXTENSIONS-- +pdo_sqlite +--CREDITS-- +YuanchengJiang +--FILE-- +setAttribute(PDO::ATTR_TIMEOUT, -1)); +var_dump($pdo->setAttribute(PDO::ATTR_TIMEOUT, intdiv(0x7fffffff, 1000) + 1)); +?> +--EXPECT-- +bool(true) +bool(false)