summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite_statement.c
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2019-06-28 12:36:33 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2019-06-28 12:36:55 +0200
commit646debaf38aa000b374b17efd0c2793d833cfcd4 (patch)
tree2c02ce30fa8bd6044f35c4d6636c0e316ccaf400 /ext/pdo_sqlite/sqlite_statement.c
parent801ab18ea7ad472cc2dc0f502efc31d175b1b832 (diff)
parent05c00a832c7b395398ef8e60edd8a7ec25439861 (diff)
downloadphp-git-646debaf38aa000b374b17efd0c2793d833cfcd4.tar.gz
Merge branch 'PHP-7.2' into PHP-7.3
* PHP-7.2: Fix bug #78192 PDO SQLite SegFault when reuse statement after schema has changed
Diffstat (limited to 'ext/pdo_sqlite/sqlite_statement.c')
-rw-r--r--ext/pdo_sqlite/sqlite_statement.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/ext/pdo_sqlite/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c
index c82e2d34eb..c51ab53956 100644
--- a/ext/pdo_sqlite/sqlite_statement.c
+++ b/ext/pdo_sqlite/sqlite_statement.c
@@ -41,6 +41,46 @@ static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
return 1;
}
+/**
+ * Change the column count on the statement.
+ *
+ * Since PHP 7.2 sqlite3_prepare_v2 is used which auto recompile prepared statement on schema change.
+ * Instead of raise an error on schema change, the result set will change, and the statement's columns must be updated.
+ *
+ * See bug #78192
+ */
+static void pdo_sqlite_stmt_set_column_count(pdo_stmt_t *stmt, int new_count)
+{
+ /* Columns not yet "described" */
+ if (!stmt->columns) {
+ stmt->column_count = new_count;
+
+ return;
+ }
+
+ /*
+ * The column count has not changed : no need to reload columns description
+ * Note: Do not handle attribute name change, without column count change
+ */
+ if (new_count == stmt->column_count) {
+ return;
+ }
+
+ /* Free previous columns to force reload description */
+ int i;
+
+ for (i = 0; i < stmt->column_count; i++) {
+ if (stmt->columns[i].name) {
+ zend_string_release(stmt->columns[i].name);
+ stmt->columns[i].name = NULL;
+ }
+ }
+
+ efree(stmt->columns);
+ stmt->columns = NULL;
+ stmt->column_count = new_count;
+}
+
static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
{
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
@@ -53,11 +93,11 @@ static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
switch (sqlite3_step(S->stmt)) {
case SQLITE_ROW:
S->pre_fetched = 1;
- stmt->column_count = sqlite3_data_count(S->stmt);
+ pdo_sqlite_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
return 1;
case SQLITE_DONE:
- stmt->column_count = sqlite3_column_count(S->stmt);
+ pdo_sqlite_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
stmt->row_count = sqlite3_changes(S->H->db);
sqlite3_reset(S->stmt);
S->done = 1;