diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index 667948fea9f1f..b098423778240 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -205,7 +205,7 @@ static int php_pdosqlite3_stream_seek(php_stream *stream, zend_off_t offset, int switch(whence) { case SEEK_CUR: if (offset < 0) { - if (sqlite3_stream->position < (size_t)(-offset)) { + if (sqlite3_stream->position < -(size_t)offset) { sqlite3_stream->position = 0; *newoffs = -1; return -1; @@ -243,7 +243,7 @@ static int php_pdosqlite3_stream_seek(php_stream *stream, zend_off_t offset, int sqlite3_stream->position = sqlite3_stream->size; *newoffs = -1; return -1; - } else if (sqlite3_stream->size < (size_t)(-offset)) { + } else if (sqlite3_stream->size < -(size_t)offset) { sqlite3_stream->position = 0; *newoffs = -1; return -1; diff --git a/ext/pdo_sqlite/tests/gh20964.phpt b/ext/pdo_sqlite/tests/gh20964.phpt new file mode 100644 index 0000000000000..65070cb1838a0 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh20964.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-20964 (fseek() on PDO SQLite blob stream with PHP_INT_MIN causes undefined behavior) +--EXTENSIONS-- +pdo_sqlite +--FILE-- +exec('CREATE TABLE test (id INTEGER PRIMARY KEY, data BLOB)'); +$db->exec("INSERT INTO test (id, data) VALUES (1, 'hello')"); + +$stream = $db->openBlob('test', 'data', 1); + +var_dump(fseek($stream, PHP_INT_MIN, SEEK_END)); + +rewind($stream); +var_dump(fseek($stream, PHP_INT_MIN, SEEK_CUR)); + +fclose($stream); +?> +--EXPECT-- +int(-1) +int(-1) diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 659de2291d86d..1764b0075addc 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -1131,7 +1131,7 @@ static int php_sqlite3_stream_seek(php_stream *stream, zend_off_t offset, int wh switch(whence) { case SEEK_CUR: if (offset < 0) { - if (sqlite3_stream->position < (size_t)(-offset)) { + if (sqlite3_stream->position < -(size_t)offset) { sqlite3_stream->position = 0; *newoffs = -1; return -1; @@ -1172,7 +1172,7 @@ static int php_sqlite3_stream_seek(php_stream *stream, zend_off_t offset, int wh sqlite3_stream->position = sqlite3_stream->size; *newoffs = -1; return -1; - } else if (sqlite3_stream->size < (size_t)(-offset)) { + } else if (sqlite3_stream->size < -(size_t)offset) { sqlite3_stream->position = 0; *newoffs = -1; return -1; diff --git a/ext/sqlite3/tests/gh20964.phpt b/ext/sqlite3/tests/gh20964.phpt new file mode 100644 index 0000000000000..852940ba983e6 --- /dev/null +++ b/ext/sqlite3/tests/gh20964.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-20964 (fseek() on SQLite3 blob stream with PHP_INT_MIN causes undefined behavior) +--EXTENSIONS-- +sqlite3 +--FILE-- +exec('CREATE TABLE test (id INTEGER PRIMARY KEY, data BLOB)'); +$db->exec("INSERT INTO test (id, data) VALUES (1, 'hello')"); + +$stream = $db->openBlob('test', 'data', 1); + +var_dump(fseek($stream, PHP_INT_MIN, SEEK_END)); + +rewind($stream); +var_dump(fseek($stream, PHP_INT_MIN, SEEK_CUR)); + +fclose($stream); +$db->close(); +?> +--EXPECT-- +int(-1) +int(-1) diff --git a/main/streams/memory.c b/main/streams/memory.c index 9cb94542df6f5..245dd3340146d 100644 --- a/main/streams/memory.c +++ b/main/streams/memory.c @@ -128,7 +128,7 @@ static int php_stream_memory_seek(php_stream *stream, zend_off_t offset, int whe switch(whence) { case SEEK_CUR: if (offset < 0) { - if (ms->fpos < (size_t)(-offset)) { + if (ms->fpos < -(size_t)offset) { ms->fpos = 0; *newoffs = -1; return -1; @@ -165,7 +165,7 @@ static int php_stream_memory_seek(php_stream *stream, zend_off_t offset, int whe stream->eof = 0; stream->fatal_error = 0; return 0; - } else if (ZSTR_LEN(ms->data) < (size_t)(-offset)) { + } else if (ZSTR_LEN(ms->data) < -(size_t)offset) { ms->fpos = 0; *newoffs = -1; return -1; diff --git a/tests/basic/gh20964.phpt b/tests/basic/gh20964.phpt new file mode 100644 index 0000000000000..2a97164c7924a --- /dev/null +++ b/tests/basic/gh20964.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-20964 (fseek() on php://memory with PHP_INT_MIN causes undefined behavior) +--FILE-- + +--EXPECT-- +int(-1) +bool(false) +int(-1) +bool(false)