Merge branch 'PHP-8.0'

* PHP-8.0:
  Fix bug #72413: Segfault with get_result and PS cursors
This commit is contained in:
Nikita Popov 2020-10-29 16:42:00 +01:00
commit dd008fd124
2 changed files with 61 additions and 22 deletions

View file

@ -109,53 +109,84 @@ if (!function_exists('mysqli_stmt_get_result'))
mysqli_stmt_close($stmt);
// get_result cannot be used in PS cursor mode
if (!$stmt = mysqli_stmt_init($link))
printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[031] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!mysqli_stmt_attr_set($stmt, MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY))
printf("[032] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!mysqli_stmt_execute($stmt))
printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$res = mysqli_stmt_get_result($stmt);
// we expect no segfault if we try to fetch a row because get_result should throw an error or return false
mysqli_fetch_assoc($res);
} catch (\mysqli_sql_exception $e) {
echo $e->getMessage() . "\n";
}
try {
$res = $stmt->get_result();
// we expect no segfault if we try to fetch a row because get_result should throw an error or return false
$res->fetch_assoc();
} catch (\mysqli_sql_exception $e) {
echo $e->getMessage() . "\n";
}
mysqli_report(MYSQLI_REPORT_OFF);
if (!$stmt = mysqli_stmt_init($link))
printf("[034] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
printf("[035] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!mysqli_stmt_execute($stmt))
printf("[036] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
$id = NULL;
$label = NULL;
if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
printf("[035] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
printf("[037] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
if (!is_object($tmp = $result = mysqli_stmt_get_result($stmt)))
printf("[036] Expecting array, got %s/%s, [%d] %s\n",
printf("[038] Expecting array, got %s/%s, [%d] %s\n",
gettype($tmp), var_export($tmp, 1),
mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
printf("[037] Expecting boolean/false, got %s/%s, [%d] %s\n",
printf("[039] Expecting boolean/false, got %s/%s, [%d] %s\n",
gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[038] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[039] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
printf("[040] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[041] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
while ($row = mysqli_fetch_assoc($result)) {
var_dump($row);
}
mysqli_free_result($result);
if (!mysqli_kill($link, mysqli_thread_id($link)))
printf("[040] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!mysqli_kill($link, mysqli_thread_id($link)))
printf("[042] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
printf("[041] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
printf("[043] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
mysqli_stmt_close($stmt);
mysqli_stmt_close($stmt);
try {
try {
mysqli_stmt_fetch($stmt);
} catch (Error $exception) {
echo $exception->getMessage() . "\n";
echo $exception->getMessage(), "\n";
}
mysqli_close($link);
mysqli_close($link);
print "done!";
print "done!";
?>
--CLEAN--
<?php
@ -165,8 +196,10 @@ if (!function_exists('mysqli_stmt_get_result'))
mysqli_stmt object is not fully initialized
mysqli_stmt object is not fully initialized
mysqli_stmt object is not fully initialized
[038] [2014] [Commands out of sync; you can't run this command now]
[039] [0] []
mysqli_stmt_get_result() cannot be used with cursors
get_result() cannot be used with cursors
[040] [2014] [Commands out of sync; you can't run this command now]
[041] [0] []
array(2) {
["id"]=>
int(1)

View file

@ -151,13 +151,19 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
}
if (stmt->cursor_exists) {
/* Silently convert buffered to unbuffered, for now */
DBG_RETURN(s->m->use_result(s));
/* Prepared statement cursors are not supported as of yet */
char * msg;
mnd_sprintf(&msg, 0, "%s() cannot be used with cursors", get_active_function_name());
SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, msg);
if (msg) {
mnd_sprintf_free(msg);
}
DBG_RETURN(NULL);
}
/* Nothing to store for UPSERT/LOAD DATA*/
if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}