diff --git a/NEWS b/NEWS index 82d364f4288..1a05e49a06a 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,10 @@ PHP NEWS . Fixed build regression on systems without C++17 compilers. (Calvin Buckley, Peter Kokot) +- MySQLnd: + . Fix bug GH-14255 (mysqli_fetch_assoc reports error from + nested query). (Kamil Tekiela) + - Opcache: . Fixed bug GH-14109 (Fix accidental persisting of internal class constant in shm). (ilutov) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index f98ab2fc15f..470918c1d96 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -731,7 +731,7 @@ void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend /* TODO: We don't have access to the connection object at this point, so we use low-level * mysqlnd APIs to access the error information. We should try to pass through the connection * object instead. */ - if (MyG(report_mode) & MYSQLI_REPORT_ERROR) { + if (MyG(report_mode) & MYSQLI_REPORT_ERROR && result->conn) { MYSQLND_CONN_DATA *conn = result->conn; unsigned error_no = conn->m->get_error_no(conn); if (error_no) { diff --git a/ext/mysqli/tests/gh14255.phpt b/ext/mysqli/tests/gh14255.phpt new file mode 100644 index 00000000000..375eda0c5b5 --- /dev/null +++ b/ext/mysqli/tests/gh14255.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug GH-14255 (mysqli_fetch_assoc reports error from nested query) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +query('SELECT 1 '); +$c = $ca->fetch_assoc(); +try { + $mysqli->query('SELECT non_existent_column'); +} catch (Exception $e) { + echo "Caught exception"."\n"; +} +$c = $ca->fetch_assoc(); + +print "done!"; +?> +--EXPECTF-- +Caught exception +done! diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 08faed6d058..ad63147861e 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -970,6 +970,13 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int bool fetched_anything; zval *row_data; + // We clean the error here because in unbuffered mode we could receive a new error + // and therefore consumers of this method are checking for errors + MYSQLND_CONN_DATA *conn = result->conn; + if (conn) { + SET_EMPTY_ERROR(conn->error_info); + } + DBG_ENTER("mysqlnd_res::fetch_into"); if (FAIL == result->m.fetch_row(result, &row_data, flags, &fetched_anything)) { RETVAL_FALSE;