Skip to content

Commit

Permalink
Fixed bug #70066
Browse files Browse the repository at this point in the history
If we fall back to emulated prepared statements, destroy S->stmt,
so the code doesn't get confused about which mode we're in.
  • Loading branch information
nikic committed Dec 9, 2020
1 parent fcfa7fd commit 106e7e4
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 11 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ PHP NEWS
(Nikita)
. Fixed bug #66878 (Multiple rowsets not returned unless PDO statement object
is unset()). (Nikita)
. Fixed bug #70066 (Unexpected "Cannot execute queries while other unbuffered
queries"). (Nikita)

- Phar:
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)
Expand Down
2 changes: 1 addition & 1 deletion ext/mysqlnd/mysqlnd_libmysql_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
#define mysql_stmt_param_count(s) mysqlnd_stmt_param_count((s))
#define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s))
#define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s))
#define mysql_stmt_close(s) mysqlnd_stmt_close((s))
#define mysql_stmt_close(s) mysqlnd_stmt_close((s), 0)
#define mysql_stmt_bind_param(s,b) mysqlnd_stmt_bind_param((s), (b))
#define mysql_stmt_bind_result(s,b) mysqlnd_stmt_bind_result((s), (b))
#define mysql_stmt_errno(s) mysqlnd_stmt_errno((s))
Expand Down
11 changes: 5 additions & 6 deletions ext/pdo_mysql/mysql_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,17 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
}

if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
if (nsql) {
efree(nsql);
}
/* TODO: might need to pull statement specific info here? */
/* if the query isn't supported by the protocol, fallback to emulation */
if (mysql_errno(H->server) == 1295) {
if (nsql) {
efree(nsql);
}
mysql_stmt_close(S->stmt);
S->stmt = NULL;
goto fallback;
}
pdo_mysql_error(dbh);
if (nsql) {
efree(nsql);
}
PDO_DBG_RETURN(0);
}
if (nsql) {
Expand Down
6 changes: 2 additions & 4 deletions ext/pdo_mysql/mysql_statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@
#ifdef PDO_USE_MYSQLND
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_mysqlnd(stmt)
# define pdo_free_bound_result(res) zval_ptr_dtor(res.zv)
# define pdo_mysql_stmt_close(stmt) mysqlnd_stmt_close(stmt, 0)
#else
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_libmysql(stmt)
# define pdo_free_bound_result(res) efree(res.buffer)
# define pdo_mysql_stmt_close(stmt) mysql_stmt_close(stmt)
#endif


Expand All @@ -56,7 +54,7 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
S->einfo.errmsg = NULL;
}
if (S->stmt) {
pdo_mysql_stmt_close(S->stmt);
mysql_stmt_close(S->stmt);
S->stmt = NULL;
}

Expand Down Expand Up @@ -363,7 +361,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
}

#ifdef PDO_USE_MYSQLND
if (!H->emulate_prepare) {
if (S->stmt) {
if (mysqlnd_stmt_next_result(S->stmt)) {
pdo_mysql_error_stmt(stmt);
S->done = 1;
Expand Down
27 changes: 27 additions & 0 deletions ext/pdo_mysql/tests/bug70066.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
Bug #70066: Unexpected "Cannot execute queries while other unbuffered queries"
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
MySQLPDOTest::skip();
?>
--FILE--
<?php

require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');

$pdo = MySQLPDOTest::factory();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);

$db = $pdo->query('SELECT DATABASE()')->fetchColumn(0);
// USE is not supported in the prepared statement protocol,
// so this will fall back to emulation.
$pdo->query('USE ' . $db);

?>
===DONE===
--EXPECT--
===DONE===

0 comments on commit 106e7e4

Please sign in to comment.