diff --git a/ext/mysqli/tests/gh11550.phpt b/ext/mysqli/tests/gh11550.phpt new file mode 100644 index 0000000000000..6ed02ec91d51f --- /dev/null +++ b/ext/mysqli/tests/gh11550.phpt @@ -0,0 +1,70 @@ +--TEST-- +Bug GH-11550 (MySQL Statement has a empty query result when the response field has changed, also Segmentation fault) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +query(<<<'SQL' +CREATE TABLE `test_gh11550` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +SQL); +$link->query(<<<'SQL' +INSERT INTO `test_gh11550` (`name`) VALUES ('test1'); +SQL); + +$stmt = $link->prepare('select * from test_gh11550'); +var_dump('mysqli-1:', $stmt->execute(), $stmt->get_result()->fetch_all()); + +$link->query(<<<'SQL' +ALTER TABLE `test_gh11550` +ADD COLUMN `a` varchar(255) NOT NULL DEFAULT ''; +SQL); + +var_dump('mysqli-2:', $stmt->execute(), $stmt->get_result()->fetch_all()); +echo 'Done'; +?> +--CLEAN-- +query('DROP TABLE IF EXISTS test_gh11550'); +?> +--EXPECT-- +string(9) "mysqli-1:" +bool(true) +array(1) { + [0]=> + array(2) { + [0]=> + int(1) + [1]=> + string(5) "test1" + } +} +string(9) "mysqli-2:" +bool(true) +array(1) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + string(5) "test1" + [2]=> + string(0) "" + } +} +Done diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index f2b98a2bc2354..b1a400499781a 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -286,8 +286,12 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s) COM_STMT_EXECUTE (even if it is not necessary), so either this or previous branch always works. */ + if (rset_header.field_count != stmt->result->field_count) { + stmt->result->m.free_result(stmt->result, TRUE); + stmt->result = conn->m->result_init(rset_header.field_count); + } + result = stmt->result; } - result = stmt->result; } if (!result) { SET_OOM_ERROR(conn->error_info); diff --git a/ext/pdo_mysql/tests/gh11550.phpt b/ext/pdo_mysql/tests/gh11550.phpt new file mode 100644 index 0000000000000..5bf0b26497ca0 --- /dev/null +++ b/ext/pdo_mysql/tests/gh11550.phpt @@ -0,0 +1,82 @@ +--TEST-- +Bug GH-11550 (MySQL Statement has a empty query result when the response field has changed, also Segmentation fault) +--EXTENSIONS-- +pdo +pdo_mysql +--SKIPIF-- + +--FILE-- +exec(<<<'SQL' +CREATE TABLE `test_gh11550` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +SQL); +$pdo->exec(<<<'SQL' +INSERT INTO `test_gh11550` (`name`) VALUES ('test1'); +SQL); + +$stmt = $pdo->prepare('select * from test_gh11550'); +var_dump('PDO-1:', $stmt->execute(), $stmt->fetchAll()); + +$stmt->closeCursor(); // Optional. Segmentation fault (core dumped) + +$pdo->exec(<<<'SQL' +ALTER TABLE `test_gh11550` +ADD COLUMN `a` varchar(255) NOT NULL DEFAULT ''; +SQL); + +var_dump('PDO-2:', $stmt->execute(), $stmt->fetchAll()); +echo 'Done'; +?> +--CLEAN-- +query('DROP TABLE IF EXISTS test_gh11550'); +?> +--EXPECT-- +string(6) "PDO-1:" +bool(true) +array(1) { + [0]=> + array(4) { + ["id"]=> + int(1) + [0]=> + int(1) + ["name"]=> + string(5) "test1" + [1]=> + string(5) "test1" + } +} +string(6) "PDO-2:" +bool(true) +array(1) { + [0]=> + array(6) { + ["id"]=> + int(1) + [0]=> + int(1) + ["name"]=> + string(5) "test1" + [1]=> + string(5) "test1" + ["a"]=> + string(0) "" + [2]=> + string(0) "" + } +} +Done