Skip to content

Commit f133f00

Browse files
committed
Fix #79294: ::columnType() may fail after SQLite3Stmt::reset()
The fix for feature request #53466 did not properly handle resetting of the corresponding statement; the problem with this is that the statement does not know about its result sets. But even if we could fix this, the `complete` handling still appears to be brittle, since the `sqlite3_column_type()`docs[1] state: | If the SQL statement does not currently point to a valid row, or if | the column index is out of range, the result is undefined. Fortunately, we can use `sqlite3_data_count()` instead, since[2]: | If prepared statement P does not have results ready to return (via | calls to the sqlite3_column() family of interfaces) then | sqlite3_data_count(P) returns 0. Thus, we guard `SQLite3::columnType()` with `sqlite3_data_count()`, and completely drop updating the `php_sqlite3_result_object.complete` field, but keep it for ABI BC purposes. [1] <https://www.sqlite.org/c3ref/column_blob.html> [2] <https://www.sqlite.org/c3ref/data_count.html>
1 parent ad000a6 commit f133f00

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ PHP NEWS
2121
- PDO_ODBC:
2222
. Fixed bug #79038 (PDOStatement::nextRowset() leaks column values). (cmb)
2323

24+
- SQLite3:
25+
. Fixed bug #79294 (::columnType() may fail after SQLite3Stmt::reset()). (cmb)
26+
2427
- Standard:
2528
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
2629

ext/sqlite3/php_sqlite3_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ struct _php_sqlite3_result_object {
108108
zval stmt_obj_zval;
109109

110110
int is_prepared_statement;
111-
int complete;
111+
int complete; // unused
112112
zend_object zo;
113113
};
114114

ext/sqlite3/sqlite3.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,7 @@ PHP_METHOD(sqlite3result, columnType)
17861786
return;
17871787
}
17881788

1789-
if (result_obj->complete) {
1789+
if (!sqlite3_data_count(result_obj->stmt_obj->stmt)) {
17901790
RETURN_FALSE;
17911791
}
17921792

@@ -1841,7 +1841,6 @@ PHP_METHOD(sqlite3result, fetchArray)
18411841
break;
18421842

18431843
case SQLITE_DONE:
1844-
result_obj->complete = 1;
18451844
RETURN_FALSE;
18461845
break;
18471846

@@ -1869,8 +1868,6 @@ PHP_METHOD(sqlite3result, reset)
18691868
RETURN_FALSE;
18701869
}
18711870

1872-
result_obj->complete = 0;
1873-
18741871
RETURN_TRUE;
18751872
}
18761873
/* }}} */

ext/sqlite3/tests/bug79294.phpt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
Bug #79294 ()::columnType() may fail after SQLite3Stmt::reset())
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('sqlite3')) die('sqlite3 extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$db = new SQLite3(':memory:');
10+
$db->exec("CREATE TABLE foo (bar INT)");
11+
$db->exec("INSERT INTO foo VALUES (1)");
12+
13+
$stmt = $db->prepare("SELECT * FROM foo");
14+
$res = $stmt->execute();
15+
var_dump($res->fetchArray() !== false);
16+
var_dump($res->columnType(0));
17+
var_dump($res->fetchArray() !== false);
18+
var_dump($res->columnType(0));
19+
$stmt->reset();
20+
var_dump($res->fetchArray() !== false);
21+
var_dump($res->columnType(0));
22+
$res->reset();
23+
var_dump($res->fetchArray() !== false);
24+
var_dump($res->columnType(0));
25+
?>
26+
--EXPECT--
27+
bool(true)
28+
int(1)
29+
bool(false)
30+
bool(false)
31+
bool(true)
32+
int(1)
33+
bool(true)
34+
int(1)

0 commit comments

Comments
 (0)