From d721d1a2f6cb6f82b4d75e0f34caf21d8eecc937 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 15:15:49 +0800 Subject: [PATCH 01/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 7 +++++++ ext/pdo/pdo_stmt.c | 7 +++++++ ext/pdo/php_pdo_driver.h | 2 ++ ext/pdo/tests/bug_78227.phpt | 27 +++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 ext/pdo/tests/bug_78227.phpt diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index d53d2ca63c0d1..75ac1127f87e1 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -25,6 +25,7 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" +#include "ext/standard/php_string.h" #include "php_pdo.h" #include "php_pdo_driver.h" #include "php_pdo_int.h" @@ -566,6 +567,12 @@ PHP_METHOD(PDO, prepare) if (dbh->methods->preparer(dbh, statement, stmt, options)) { pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); + + stmt->select_all = 0; + if (php_stristr(stmt->query_string, "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && + php_stristr(stmt->query_string, "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { + stmt->select_all = 1; + } return; } diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 5320d50cf9c9f..5ff5d882d9878 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -461,6 +461,13 @@ PHP_METHOD(PDOStatement, execute) RETURN_FALSE; } if (stmt->methods->executer(stmt)) { + /* When selecting all fields, + * we have to check column name and reload columns descriptions to prevent a column name change. */ + if (stmt->select_all) { + pdo_stmt_reset_columns(stmt); + stmt->executed = 0; + } + if (!stmt->executed) { /* this is the first execute */ diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 91a60fe323244..99165dc4887c6 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -558,6 +558,8 @@ struct _pdo_stmt_t { /* if true, we've already successfully executed this statement at least * once */ unsigned executed:1; + /* if true, it means select all fields */ + unsigned select_all:1; /* if true, the statement supports placeholders and can implement * bindParam() for its prepared statements, if false, PDO should * emulate prepare and bind on its behalf */ diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt new file mode 100644 index 0000000000000..6ad99f927d248 --- /dev/null +++ b/ext/pdo/tests/bug_78227.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #78227 Prepared statements ignore RENAME COLUMN +--EXTENSIONS-- +pdo +--SKIPIF-- +exec("CREATE TABLE user (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); +$db->exec("INSERT INTO user (id, foo) VALUES (10, 'test')"); +$stmt = $db->prepare("SELECT * FROM user WHERE id = :id"); +$stmt->execute(['id' => 10]); +print_r($stmt->fetch(PDO::FETCH_ASSOC)); +$db->exec("ALTER TABLE user RENAME COLUMN foo TO bar"); +$res = $stmt->execute(['id' => 10]); +print_r($stmt->fetch(PDO::FETCH_ASSOC)); +?> +--EXPECT-- +Array +( + [id] => 10 + [foo] => test +) +Array +( + [id] => 20 + [bar] => test +) \ No newline at end of file From 8509b15f9fe18fdaf71bcedb24e0038eb1bd9a21 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 15:22:16 +0800 Subject: [PATCH 02/25] fix bug 78227 --- ext/pdo/tests/bug_78227.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 6ad99f927d248..34f91a82fe484 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -24,4 +24,4 @@ Array ( [id] => 20 [bar] => test -) \ No newline at end of file +) From e8ab09af0fb855a20108ea399f8f7b63e8d5d427 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 16:45:37 +0800 Subject: [PATCH 03/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 75ac1127f87e1..848b9740108fe 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -569,8 +569,8 @@ PHP_METHOD(PDO, prepare) pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); stmt->select_all = 0; - if (php_stristr(stmt->query_string, "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && - php_stristr(stmt->query_string, "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { + if (php_stristr(Z_STR_P(stmt->query_string), "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && + php_stristr(Z_STR_P(stmt->query_string), "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { stmt->select_all = 1; } return; From ab5e9e3fdb4b4eb57088af1ebbd7b269d4a4036a Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 16:58:52 +0800 Subject: [PATCH 04/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 848b9740108fe..422471456e35a 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -569,8 +569,8 @@ PHP_METHOD(PDO, prepare) pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); stmt->select_all = 0; - if (php_stristr(Z_STR_P(stmt->query_string), "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && - php_stristr(Z_STR_P(stmt->query_string), "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { + if (php_stristr(ZSTR_VAL(stmt->query_string), "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && + php_stristr(ZSTR_VAL(stmt->query_string), "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { stmt->select_all = 1; } return; From 20f25105d49c471015bb5f90ee308e70aaa977ba Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 17:02:50 +0800 Subject: [PATCH 05/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 422471456e35a..05a992a7c0c94 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -569,8 +569,8 @@ PHP_METHOD(PDO, prepare) pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); stmt->select_all = 0; - if (php_stristr(ZSTR_VAL(stmt->query_string), "select", sizeof(stmt->query_string) - 1, sizeof("select") - 1) && - php_stristr(ZSTR_VAL(stmt->query_string), "*", sizeof(stmt->query_string) - 1, sizeof("*") - 1)) { + if (php_stristr(ZSTR_VAL(stmt->query_string), "select", ZSTR_LEN(stmt->query_string), sizeof("select") - 1) && + php_stristr(ZSTR_VAL(stmt->query_string), "*", ZSTR_LEN(stmt->query_string), sizeof("*") - 1)) { stmt->select_all = 1; } return; From efb4f0d627cd070c684bf1f213260318f6e9629c Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 17:58:48 +0800 Subject: [PATCH 06/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 05a992a7c0c94..8e9d24c340aa0 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -569,8 +569,14 @@ PHP_METHOD(PDO, prepare) pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); stmt->select_all = 0; - if (php_stristr(ZSTR_VAL(stmt->query_string), "select", ZSTR_LEN(stmt->query_string), sizeof("select") - 1) && - php_stristr(ZSTR_VAL(stmt->query_string), "*", ZSTR_LEN(stmt->query_string), sizeof("*") - 1)) { + + char *action = estrdup("select"); + char *wildcard = estrdup("*"); + char *query_string_val = ZSTR_VAL(stmt->query_string); + size_t query_string_len = ZSTR_LEN(stmt->query_string); + + if (php_stristr(query_string_val, action, query_string_len, sizeof("select") - 1) && + php_stristr(query_string_val, wildcard, query_string_len, sizeof("*") - 1)) { stmt->select_all = 1; } return; From b758023323dfdb92457c8eaf1fd97214a211a66a Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 18:08:28 +0800 Subject: [PATCH 07/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 2 ++ ext/pdo/pdo_stmt.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 8e9d24c340aa0..c4197d9b810f6 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -579,6 +579,8 @@ PHP_METHOD(PDO, prepare) php_stristr(query_string_val, wildcard, query_string_len, sizeof("*") - 1)) { stmt->select_all = 1; } + efree(action); + efree(wildcard); return; } diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 5ff5d882d9878..21b28613ea64c 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -463,7 +463,7 @@ PHP_METHOD(PDOStatement, execute) if (stmt->methods->executer(stmt)) { /* When selecting all fields, * we have to check column name and reload columns descriptions to prevent a column name change. */ - if (stmt->select_all) { + if (stmt->select_all && stmt->columns) { pdo_stmt_reset_columns(stmt); stmt->executed = 0; } From 00b3feac8c1f248d3151221f5994fbba3c246c21 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 18:22:47 +0800 Subject: [PATCH 08/25] fix bug 78227 --- ext/pdo/pdo_stmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 21b28613ea64c..8d1e071c93964 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -464,7 +464,7 @@ PHP_METHOD(PDOStatement, execute) /* When selecting all fields, * we have to check column name and reload columns descriptions to prevent a column name change. */ if (stmt->select_all && stmt->columns) { - pdo_stmt_reset_columns(stmt); + php_pdo_stmt_set_column_count(stmt, stmt->column_count); stmt->executed = 0; } From bfd26f3dfc27ba8b1f3f232f2b2245bd51a1afd3 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sun, 12 Sep 2021 18:35:29 +0800 Subject: [PATCH 09/25] fix bug 78227 --- ext/pdo/pdo_stmt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 8d1e071c93964..e6f374ba237d2 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -464,7 +464,9 @@ PHP_METHOD(PDOStatement, execute) /* When selecting all fields, * we have to check column name and reload columns descriptions to prevent a column name change. */ if (stmt->select_all && stmt->columns) { - php_pdo_stmt_set_column_count(stmt, stmt->column_count); + int count = stmt->column_count; + pdo_stmt_reset_columns(stmt); + stmt->column_count = count; stmt->executed = 0; } From 5b8dd49bf43cec9baea79fc646bced93cf89d381 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 22:24:29 +0800 Subject: [PATCH 10/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 1 - ext/pdo/tests/bug_78227.phpt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index c4197d9b810f6..6f350e61bcce4 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -569,7 +569,6 @@ PHP_METHOD(PDO, prepare) pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); stmt->select_all = 0; - char *action = estrdup("select"); char *wildcard = estrdup("*"); char *query_string_val = ZSTR_VAL(stmt->query_string); diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 34f91a82fe484..7540d66cc300e 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -2,7 +2,7 @@ Bug #78227 Prepared statements ignore RENAME COLUMN --EXTENSIONS-- pdo ---SKIPIF-- +--FILE-- exec("CREATE TABLE user (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); From c2f8c0ac65c6db58ec51b6c99633b4e2fe1f0c3f Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 23:05:04 +0800 Subject: [PATCH 11/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 6f350e61bcce4..db4cf630e7c10 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -487,6 +487,29 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt } /* }}} */ +static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ +{ + stmt->select_all = 0; + char *action = estrdup("select"); + char *wildcard = estrdup("*"); + + zend_string *statement = zend_string_dup(stmt->query_string, 0); + char *query_string_val = ZSTR_VAL(statement)); + size_t query_string_len = ZSTR_LEN(statement); + php_strtolower(query_string_val, query_string_len); + + if (php_memnstr(query_string_val, action, sizeof("select") - 1, query_string_val + query_string_len) && + php_memnstr(query_string_val, wildcard, sizeof("*") - 1, query_string_val + query_string_len) + ) { + stmt->select_all = 1; + } + + efree(action); + efree(wildcard); + zend_string_release(statement); +} +/* }}} */ + /* {{{ Prepares a statement for execution and returns a statement object */ PHP_METHOD(PDO, prepare) { @@ -568,18 +591,7 @@ PHP_METHOD(PDO, prepare) if (dbh->methods->preparer(dbh, statement, stmt, options)) { pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); - stmt->select_all = 0; - char *action = estrdup("select"); - char *wildcard = estrdup("*"); - char *query_string_val = ZSTR_VAL(stmt->query_string); - size_t query_string_len = ZSTR_LEN(stmt->query_string); - if (php_stristr(query_string_val, action, query_string_len, sizeof("select") - 1) && - php_stristr(query_string_val, wildcard, query_string_len, sizeof("*") - 1)) { - stmt->select_all = 1; - } - efree(action); - efree(wildcard); return; } From a3bf6e3de7141e2fddbbb8f1a6ea4e8a89f72d68 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 23:07:44 +0800 Subject: [PATCH 12/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index db4cf630e7c10..aa1143f1fbcdf 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -490,22 +490,18 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { stmt->select_all = 0; - char *action = estrdup("select"); - char *wildcard = estrdup("*"); zend_string *statement = zend_string_dup(stmt->query_string, 0); char *query_string_val = ZSTR_VAL(statement)); size_t query_string_len = ZSTR_LEN(statement); php_strtolower(query_string_val, query_string_len); - if (php_memnstr(query_string_val, action, sizeof("select") - 1, query_string_val + query_string_len) && - php_memnstr(query_string_val, wildcard, sizeof("*") - 1, query_string_val + query_string_len) + if (php_memnstr(query_string_val, "select", sizeof("select") - 1, query_string_val + query_string_len) && + php_memnstr(query_string_val, "*", sizeof("*") - 1, query_string_val + query_string_len) ) { stmt->select_all = 1; } - efree(action); - efree(wildcard); zend_string_release(statement); } /* }}} */ From 0df9f96aec6c63c50ef74167008af8eecf442d0f Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 23:10:19 +0800 Subject: [PATCH 13/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index aa1143f1fbcdf..39478d4576ba0 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -586,8 +586,7 @@ PHP_METHOD(PDO, prepare) if (dbh->methods->preparer(dbh, statement, stmt, options)) { pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); - - + pdo_stmt_check_select_all(stmt); return; } From b6ec42517ddafa0d86abe04827753f8891bf6267 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 23:15:41 +0800 Subject: [PATCH 14/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 39478d4576ba0..5fa5df9ce343c 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -489,16 +489,14 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { - stmt->select_all = 0; - zend_string *statement = zend_string_dup(stmt->query_string, 0); char *query_string_val = ZSTR_VAL(statement)); size_t query_string_len = ZSTR_LEN(statement); + const char *end = query_string_val + query_string_len; php_strtolower(query_string_val, query_string_len); - if (php_memnstr(query_string_val, "select", sizeof("select") - 1, query_string_val + query_string_len) && - php_memnstr(query_string_val, "*", sizeof("*") - 1, query_string_val + query_string_len) - ) { + stmt->select_all = 0; + if (php_memnstr(query_string_val, "select", sizeof("select") - 1, end) && php_memnstr(query_string_val, "*", sizeof("*") - 1, end)) { stmt->select_all = 1; } From 80e645ce095cd557adda59aa5082c4ef3e499f78 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 13 Sep 2021 23:23:46 +0800 Subject: [PATCH 15/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 5fa5df9ce343c..05616ed047254 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -489,8 +489,9 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { + /* Avoid polluting stmt->query_string */ zend_string *statement = zend_string_dup(stmt->query_string, 0); - char *query_string_val = ZSTR_VAL(statement)); + char *query_string_val = ZSTR_VAL(statement); size_t query_string_len = ZSTR_LEN(statement); const char *end = query_string_val + query_string_len; php_strtolower(query_string_val, query_string_len); From e087b19258488d1e4217ce4b19088ac87076cad0 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Tue, 14 Sep 2021 10:50:18 +0800 Subject: [PATCH 16/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 05616ed047254..39cc9844c33be 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -489,15 +489,16 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { - /* Avoid polluting stmt->query_string */ - zend_string *statement = zend_string_dup(stmt->query_string, 0); - char *query_string_val = ZSTR_VAL(statement); - size_t query_string_len = ZSTR_LEN(statement); - const char *end = query_string_val + query_string_len; - php_strtolower(query_string_val, query_string_len); + /* Avoid modifying stmt->query_string */ + zend_string *statement = zend_string_init(ZSTR_VAL(stmt->query_string), ZSTR_LEN(stmt->query_string), 0); + + char *statement_val = ZSTR_VAL(statement_val); + size_t statement_len = ZSTR_LEN(statement_val); + char *end = statement_val + statement_len; + php_strtolower(statement_val, statement_len); stmt->select_all = 0; - if (php_memnstr(query_string_val, "select", sizeof("select") - 1, end) && php_memnstr(query_string_val, "*", sizeof("*") - 1, end)) { + if (php_memnstr(statement_val, "select", sizeof("select") - 1, end) && php_memnstr(statement_val, "*", sizeof("*") - 1, end)) { stmt->select_all = 1; } From 87fa99c096f3425300d64cb39a681e1d8f8d3505 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:01:38 +0800 Subject: [PATCH 17/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 39cc9844c33be..da0b53c936a3c 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -491,7 +491,6 @@ static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { /* Avoid modifying stmt->query_string */ zend_string *statement = zend_string_init(ZSTR_VAL(stmt->query_string), ZSTR_LEN(stmt->query_string), 0); - char *statement_val = ZSTR_VAL(statement_val); size_t statement_len = ZSTR_LEN(statement_val); char *end = statement_val + statement_len; From 914a145ffd8fc24539851a7da3b47fa50616bff7 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:10:12 +0800 Subject: [PATCH 18/25] fix bug 78227 --- ext/pdo/pdo_dbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index da0b53c936a3c..d324708558ff5 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -491,8 +491,8 @@ static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ { /* Avoid modifying stmt->query_string */ zend_string *statement = zend_string_init(ZSTR_VAL(stmt->query_string), ZSTR_LEN(stmt->query_string), 0); - char *statement_val = ZSTR_VAL(statement_val); - size_t statement_len = ZSTR_LEN(statement_val); + char *statement_val = ZSTR_VAL(statement); + size_t statement_len = ZSTR_LEN(statement); char *end = statement_val + statement_len; php_strtolower(statement_val, statement_len); From c6fce818534bc0b39ba713fc1140383b8b9193bc Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:20:11 +0800 Subject: [PATCH 19/25] fix bug 78227 --- ext/pdo/tests/bug_78227.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 7540d66cc300e..2e6705d5ae646 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -22,6 +22,6 @@ Array ) Array ( - [id] => 20 + [id] => 10 [bar] => test -) +) \ No newline at end of file From 57941463c8c3315b111c786f4212895e99943856 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Wed, 15 Sep 2021 13:14:01 +0800 Subject: [PATCH 20/25] rename pdo_stmt_check_select_all to pdo_stmt_set_select_all --- ext/pdo/pdo_dbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index d324708558ff5..30316bd11aa10 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -487,7 +487,7 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt } /* }}} */ -static void pdo_stmt_check_select_all(pdo_stmt_t *stmt) /* {{{ */ +static void pdo_stmt_set_select_all(pdo_stmt_t *stmt) /* {{{ */ { /* Avoid modifying stmt->query_string */ zend_string *statement = zend_string_init(ZSTR_VAL(stmt->query_string), ZSTR_LEN(stmt->query_string), 0); @@ -585,7 +585,7 @@ PHP_METHOD(PDO, prepare) if (dbh->methods->preparer(dbh, statement, stmt, options)) { pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); - pdo_stmt_check_select_all(stmt); + pdo_stmt_set_select_all(stmt); return; } From 836fed04bcbc8d701862fd46fc424bd728676fe2 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Thu, 16 Sep 2021 10:07:26 +0800 Subject: [PATCH 21/25] change unsigned _reserved:29 to unsigned _reserved:28 perfect unit test --- ext/pdo/php_pdo_driver.h | 2 +- ext/pdo/tests/bug_78227.phpt | 50 +++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 99165dc4887c6..8323140b677e8 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -565,7 +565,7 @@ struct _pdo_stmt_t { * emulate prepare and bind on its behalf */ unsigned supports_placeholders:2; - unsigned _reserved:29; + unsigned _reserved:28; /* the number of columns in the result set; not valid until after * the statement has been executed at least once. In some cases, might diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 2e6705d5ae646..28ff24e3b6d6d 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -2,17 +2,49 @@ Bug #78227 Prepared statements ignore RENAME COLUMN --EXTENSIONS-- pdo +--SKIPIF-- + --FILE-- exec("CREATE TABLE user (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); -$db->exec("INSERT INTO user (id, foo) VALUES (10, 'test')"); -$stmt = $db->prepare("SELECT * FROM user WHERE id = :id"); -$stmt->execute(['id' => 10]); -print_r($stmt->fetch(PDO::FETCH_ASSOC)); -$db->exec("ALTER TABLE user RENAME COLUMN foo TO bar"); -$res = $stmt->execute(['id' => 10]); -print_r($stmt->fetch(PDO::FETCH_ASSOC)); + if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); + require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; + $db = PDOTest::factory(); + $db->exec("CREATE TABLE bug_78227 (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); + $db->exec("INSERT INTO bug_78227 (id, foo) VALUES (10, 'test')"); + $stmt = $db->prepare("SELECT * FROM bug_78227 WHERE id = :id"); + $stmt->execute(['id' => 10]); + print_r($stmt->fetch(PDO::FETCH_ASSOC)); + + $driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME); + switch(true){ + case "mysql" == $driver: + $db->exec("ALTER TABLE bug_78227 change foo bat varchar(20)"); + break; + case "sqlite" == $driver: + case "oci" == $driver: + case "pgsql" == $driver: + $db->exec("ALTER TABLE bug_78227 rename column foo to bar"); + break; + case "firebird" == $driver: + $db->exec("ALTER TABLE bug_78227 alter column foo to bar"); + break; + case "mssql" == $driver: + $db->exec("execute sp_rename 'bug_78227.foo','bar','column'"); + break; + case "sybase" == $driver: + $db->exec("sp_rename 'bug_78227.foo','bar','column'"); + break; + default: + die('skip unknown driver'); + } + + $res = $stmt->execute(['id' => 10]); + print_r($stmt->fetch(PDO::FETCH_ASSOC)); ?> --EXPECT-- Array From 83cdadc3ad59ee4a0e7a91e1224e5cbf9f855609 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Thu, 16 Sep 2021 11:47:30 +0800 Subject: [PATCH 22/25] perfect unit test --- ext/pdo/tests/bug_78227.phpt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 28ff24e3b6d6d..7df18aa129125 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -14,6 +14,8 @@ pdo if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); + $db->exec("drop table bug_78227"); + $db->exec("CREATE TABLE bug_78227 (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); $db->exec("INSERT INTO bug_78227 (id, foo) VALUES (10, 'test')"); $stmt = $db->prepare("SELECT * FROM bug_78227 WHERE id = :id"); @@ -46,6 +48,13 @@ pdo $res = $stmt->execute(['id' => 10]); print_r($stmt->fetch(PDO::FETCH_ASSOC)); ?> +--CLEAN-- +exec("drop table bug_78227"); +?> --EXPECT-- Array ( From b1f4e59521603b4a27fd8ac95c6a990a9fecc653 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Thu, 16 Sep 2021 14:32:40 +0800 Subject: [PATCH 23/25] unit test --- ext/pdo/tests/bug_78227.phpt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 7df18aa129125..020fd0895d16e 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -14,7 +14,7 @@ pdo if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); - $db->exec("drop table bug_78227"); + @$db->exec("drop table bug_78227"); $db->exec("CREATE TABLE bug_78227 (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); $db->exec("INSERT INTO bug_78227 (id, foo) VALUES (10, 'test')"); @@ -28,6 +28,8 @@ pdo $db->exec("ALTER TABLE bug_78227 change foo bat varchar(20)"); break; case "sqlite" == $driver: + $db->exec("ALTER TABLE bug_78227 rename foo to bar"); + break; case "oci" == $driver: case "pgsql" == $driver: $db->exec("ALTER TABLE bug_78227 rename column foo to bar"); @@ -36,13 +38,13 @@ pdo $db->exec("ALTER TABLE bug_78227 alter column foo to bar"); break; case "mssql" == $driver: + case "dblib" == $driver: + case "odbc" == $driver: $db->exec("execute sp_rename 'bug_78227.foo','bar','column'"); break; case "sybase" == $driver: $db->exec("sp_rename 'bug_78227.foo','bar','column'"); break; - default: - die('skip unknown driver'); } $res = $stmt->execute(['id' => 10]); From cd969fbc81979e3327ef1eb8c6fdf6ea265fc8b7 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 16 Sep 2021 19:36:57 +0800 Subject: [PATCH 24/25] fix cached plan must not change result type of pgsql --- ext/pdo/tests/bug_78227.phpt | 11 +++++++---- ext/pdo_pgsql/pgsql_statement.c | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 020fd0895d16e..132ec95602d1c 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -16,8 +16,11 @@ pdo $db = PDOTest::factory(); @$db->exec("drop table bug_78227"); - $db->exec("CREATE TABLE bug_78227 (id INTEGER PRIMARY KEY NOT NULL, foo VARCHAR(255) NOT NULL)"); - $db->exec("INSERT INTO bug_78227 (id, foo) VALUES (10, 'test')"); + $db->exec("CREATE TABLE bug_78227 (id int, foo varchar(20))"); + + $stmt = $db->prepare("INSERT INTO bug_78227 (id, foo) VALUES (?, ?)"); + $stmt->execute([10, 'test']); + $stmt = $db->prepare("SELECT * FROM bug_78227 WHERE id = :id"); $stmt->execute(['id' => 10]); print_r($stmt->fetch(PDO::FETCH_ASSOC)); @@ -25,7 +28,7 @@ pdo $driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME); switch(true){ case "mysql" == $driver: - $db->exec("ALTER TABLE bug_78227 change foo bat varchar(20)"); + $db->exec("ALTER TABLE bug_78227 change foo bar varchar(20)"); break; case "sqlite" == $driver: $db->exec("ALTER TABLE bug_78227 rename foo to bar"); @@ -55,7 +58,7 @@ pdo if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); - $db->exec("drop table bug_78227"); + @$db->exec("drop table bug_78227"); ?> --EXPECT-- Array diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 03ac14c32db9a..9a14254f9642a 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -173,7 +173,10 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) } else if (S->stmt_name) { /* using a prepared statement */ - if (!S->is_prepared) { + /* it will issue a warning that cached plan must not change result type if altering the table, + * so wo have to reset S->result to solve it. + * stmt->select_all means select all column.*/ + if (!S->is_prepared || stmt->select_all) { stmt_retry: /* we deferred the prepare until now, because we didn't * know anything about the parameter types; now we do */ From 73329e8634a50a287f05a352ae8b508edd4d045c Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 16 Sep 2021 21:02:09 +0800 Subject: [PATCH 25/25] fix cached plan must not change result type of pgsql --- ext/pdo/tests/bug_78227.phpt | 90 ++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/ext/pdo/tests/bug_78227.phpt b/ext/pdo/tests/bug_78227.phpt index 132ec95602d1c..47ad119ef5441 100644 --- a/ext/pdo/tests/bug_78227.phpt +++ b/ext/pdo/tests/bug_78227.phpt @@ -4,61 +4,61 @@ Bug #78227 Prepared statements ignore RENAME COLUMN pdo --SKIPIF-- --FILE-- exec("drop table bug_78227"); +if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); +require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; +$db = PDOTest::factory(); +@$db->exec("drop table test"); - $db->exec("CREATE TABLE bug_78227 (id int, foo varchar(20))"); +$db->exec("CREATE TABLE test (id int, foo varchar(20))"); - $stmt = $db->prepare("INSERT INTO bug_78227 (id, foo) VALUES (?, ?)"); - $stmt->execute([10, 'test']); +$stmt = $db->prepare("INSERT INTO test (id, foo) VALUES (?, ?)"); +$stmt->execute([10, 'test']); - $stmt = $db->prepare("SELECT * FROM bug_78227 WHERE id = :id"); - $stmt->execute(['id' => 10]); - print_r($stmt->fetch(PDO::FETCH_ASSOC)); +$stmt = $db->prepare("SELECT * FROM test WHERE id = :id"); +$stmt->execute(['id' => 10]); +print_r($stmt->fetch(PDO::FETCH_ASSOC)); - $driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME); - switch(true){ - case "mysql" == $driver: - $db->exec("ALTER TABLE bug_78227 change foo bar varchar(20)"); - break; - case "sqlite" == $driver: - $db->exec("ALTER TABLE bug_78227 rename foo to bar"); - break; - case "oci" == $driver: - case "pgsql" == $driver: - $db->exec("ALTER TABLE bug_78227 rename column foo to bar"); - break; - case "firebird" == $driver: - $db->exec("ALTER TABLE bug_78227 alter column foo to bar"); - break; - case "mssql" == $driver: - case "dblib" == $driver: - case "odbc" == $driver: - $db->exec("execute sp_rename 'bug_78227.foo','bar','column'"); - break; - case "sybase" == $driver: - $db->exec("sp_rename 'bug_78227.foo','bar','column'"); - break; - } +$driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME); +switch(true){ + case "mysql" == $driver: + $db->exec("ALTER TABLE test change foo bar varchar(20)"); + break; + case "sqlite" == $driver: + $db->exec("ALTER TABLE test rename column foo to bar"); + break; + case "oci" == $driver: + case "pgsql" == $driver: + $db->exec("ALTER TABLE test rename column foo to bar"); + break; + case "firebird" == $driver: + $db->exec("ALTER TABLE test alter column foo to bar"); + break; + case "mssql" == $driver: + case "dblib" == $driver: + case "odbc" == $driver: + $db->exec("execute sp_rename 'test.foo','bar','column'"); + break; + case "sybase" == $driver: + $db->exec("sp_rename 'test.foo','bar','column'"); + break; +} - $res = $stmt->execute(['id' => 10]); - print_r($stmt->fetch(PDO::FETCH_ASSOC)); +$res = $stmt->execute(['id' => 10]); +print_r($stmt->fetch(PDO::FETCH_ASSOC)); ?> --CLEAN-- exec("drop table bug_78227"); +if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); +require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; +$db = PDOTest::factory(); +@$db->exec("drop table test"); ?> --EXPECT-- Array @@ -70,4 +70,4 @@ Array ( [id] => 10 [bar] => test -) \ No newline at end of file +)