com php-src: Fix bug #69899: NEWS ext/mysqli/tests/bug69899.phpt ext/mysqlnd/mysqlnd_ps.c
| From: | Nikita Popov | Date: | Thu, 12 Jan 2017 20:13:39 +0000 |
| Subject: | com php-src: Fix bug #69899: NEWS ext/mysqli/tests/bug69899.phpt ext/mysqlnd/mysqlnd_ps.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-96701@lists.php.net to get a copy of this message | ||
Commit: bd75f9e61375c7632bb55b0d49b470ecd94e8ec7
Author: rfussenegger <richard.fussenegger@trivago.com> Fri, 30 Sep 2016 10:49:08
+0200
Committer: Nikita Popov <nikita.ppv@gmail.com> Thu, 12 Jan 2017 21:13:39 +0100
Parents: 1ee1f79e27fb4006d0400b38163b2ec0786fd130
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=bd75f9e61375c7632bb55b0d49b470ecd94e8ec7
Log:
Fix bug #69899
Bugs:
https://bugs.php.net/69899
Changed paths:
M NEWS
A ext/mysqli/tests/bug69899.phpt
M ext/mysqlnd/mysqlnd_ps.c
Diff:
diff --git a/NEWS b/NEWS
index 3338ba9..efbee5e 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ PHP NEWS
. Fixed bug #67583 (double fastcgi_end_request on max_children limit).
(Dmitry Saprykin)
+- Mysqlnd:
+ . Fixed bug #69899 (segfault on close() after free_result() with mysqlnd).
+ (Richard Fussenegger)
+
- OpenSSL:
. Fixed bug #71519 (add serial hex to return value array). (xrobau)
diff --git a/ext/mysqli/tests/bug69899.phpt b/ext/mysqli/tests/bug69899.phpt
new file mode 100644
index 0000000..177b5e3
--- /dev/null
+++ b/ext/mysqli/tests/bug69899.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #69899: Segfault on stmt close after free_result with mysqlnd.
+--DESCRIPTION--
+The segfault happens only if the database connection was already closed and
+free_result is called on a prepared statement followed by closing that
+statement. This is due to mysqlnd_stmt::free_result (mysqlnd_ps.c) which
+unconditionally sets the connection of the statement to ready, despite the fact
+that it might already be closed.
+--SKIPIF--
+<?php
+require_once __DIR__ . '/skipif.inc';
+require_once __DIR__ . '/skipifconnectfailure.inc';
+require_once __DIR__ . '/connect.inc';
+if (!$IS_MYSQLND) {
+ die('mysqlnd only');
+}
+?>
+--FILE--
+<?php
+
+require_once __DIR__ . '/connect.inc';
+
+mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
+
+$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket);
+$stmt = $mysqli->prepare('SELECT 1');
+
+var_dump(
+ $mysqli->close(),
+ $stmt->free_result(),
+ $stmt->close()
+);
+
+?>
+--EXPECT--
+bool(true)
+NULL
+bool(true)
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 670ea99..2631e4a 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -2005,8 +2005,9 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s)
stmt->state = MYSQLND_STMT_PREPARED;
}
- /* Line is free! */
- CONN_SET_STATE(stmt->conn, CONN_READY);
+ if (CONN_GET_STATE(stmt->conn) != CONN_QUIT_SENT) {
+ CONN_SET_STATE(stmt->conn, CONN_READY);
+ }
DBG_RETURN(PASS);
}