summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-02-21 13:24:37 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-02-21 13:36:29 +0100
commitf133f0024ec801dc9636ee5bf84a93de1300d4b2 (patch)
treef3bed38ec62e41c00844766b009eb300620166bd
parentad000a63e8a1b6aacbff5d7bd806abfe388c18eb (diff)
downloadphp-git-f133f0024ec801dc9636ee5bf84a93de1300d4b2.tar.gz
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>
-rw-r--r--NEWS3
-rw-r--r--ext/sqlite3/php_sqlite3_structs.h2
-rw-r--r--ext/sqlite3/sqlite3.c5
-rw-r--r--ext/sqlite3/tests/bug79294.phpt34
4 files changed, 39 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 4d154b2be9..c5eaa64e77 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,9 @@ PHP NEWS
- PDO_ODBC:
. Fixed bug #79038 (PDOStatement::nextRowset() leaks column values). (cmb)
+- SQLite3:
+ . Fixed bug #79294 (::columnType() may fail after SQLite3Stmt::reset()). (cmb)
+
- Standard:
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
diff --git a/ext/sqlite3/php_sqlite3_structs.h b/ext/sqlite3/php_sqlite3_structs.h
index bd65063906..5a25af61e1 100644
--- a/ext/sqlite3/php_sqlite3_structs.h
+++ b/ext/sqlite3/php_sqlite3_structs.h
@@ -108,7 +108,7 @@ struct _php_sqlite3_result_object {
zval stmt_obj_zval;
int is_prepared_statement;
- int complete;
+ int complete; // unused
zend_object zo;
};
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index 6ae049a740..c2b4fa8bca 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -1786,7 +1786,7 @@ PHP_METHOD(sqlite3result, columnType)
return;
}
- if (result_obj->complete) {
+ if (!sqlite3_data_count(result_obj->stmt_obj->stmt)) {
RETURN_FALSE;
}
@@ -1841,7 +1841,6 @@ PHP_METHOD(sqlite3result, fetchArray)
break;
case SQLITE_DONE:
- result_obj->complete = 1;
RETURN_FALSE;
break;
@@ -1869,8 +1868,6 @@ PHP_METHOD(sqlite3result, reset)
RETURN_FALSE;
}
- result_obj->complete = 0;
-
RETURN_TRUE;
}
/* }}} */
diff --git a/ext/sqlite3/tests/bug79294.phpt b/ext/sqlite3/tests/bug79294.phpt
new file mode 100644
index 0000000000..5538e3886b
--- /dev/null
+++ b/ext/sqlite3/tests/bug79294.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #79294 ()::columnType() may fail after SQLite3Stmt::reset())
+--SKIPIF--
+<?php
+if (!extension_loaded('sqlite3')) die('sqlite3 extension not available');
+?>
+--FILE--
+<?php
+$db = new SQLite3(':memory:');
+$db->exec("CREATE TABLE foo (bar INT)");
+$db->exec("INSERT INTO foo VALUES (1)");
+
+$stmt = $db->prepare("SELECT * FROM foo");
+$res = $stmt->execute();
+var_dump($res->fetchArray() !== false);
+var_dump($res->columnType(0));
+var_dump($res->fetchArray() !== false);
+var_dump($res->columnType(0));
+$stmt->reset();
+var_dump($res->fetchArray() !== false);
+var_dump($res->columnType(0));
+$res->reset();
+var_dump($res->fetchArray() !== false);
+var_dump($res->columnType(0));
+?>
+--EXPECT--
+bool(true)
+int(1)
+bool(false)
+bool(false)
+bool(true)
+int(1)
+bool(true)
+int(1)