diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2019-06-28 12:36:33 +0200 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2019-06-28 12:36:55 +0200 |
commit | 646debaf38aa000b374b17efd0c2793d833cfcd4 (patch) | |
tree | 2c02ce30fa8bd6044f35c4d6636c0e316ccaf400 /ext/pdo_sqlite/sqlite_statement.c | |
parent | 801ab18ea7ad472cc2dc0f502efc31d175b1b832 (diff) | |
parent | 05c00a832c7b395398ef8e60edd8a7ec25439861 (diff) | |
download | php-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.c | 44 |
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; |