From: Nikita Popov Date: Wed, 9 Dec 2020 16:24:30 +0000 (+0100) Subject: Fixed bug #70066 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=106e7e4bca7c0fd975eb219b18e3c34957ba8657;p=php Fixed bug #70066 If we fall back to emulated prepared statements, destroy S->stmt, so the code doesn't get confused about which mode we're in. --- diff --git a/NEWS b/NEWS index d8b035b7f8..654544bb8f 100644 --- a/NEWS +++ b/NEWS @@ -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) diff --git a/ext/mysqlnd/mysqlnd_libmysql_compat.h b/ext/mysqlnd/mysqlnd_libmysql_compat.h index df4b96eec3..092659e9dd 100644 --- a/ext/mysqlnd/mysqlnd_libmysql_compat.h +++ b/ext/mysqlnd/mysqlnd_libmysql_compat.h @@ -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)) diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index eafd28463f..764c453438 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -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) { diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index f6d460c82b..005f5890ab 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -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 @@ -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; } @@ -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; diff --git a/ext/pdo_mysql/tests/bug70066.phpt b/ext/pdo_mysql/tests/bug70066.phpt new file mode 100644 index 0000000000..54660fb3f6 --- /dev/null +++ b/ext/pdo_mysql/tests/bug70066.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #70066: Unexpected "Cannot execute queries while other unbuffered queries" +--SKIPIF-- + +--FILE-- +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===