summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2017-01-12 21:14:42 +0100
committerNikita Popov <nikita.ppv@gmail.com>2017-01-12 21:15:57 +0100
commitda5e09ad0389f53cdc78591442a3df1ff54c6ff0 (patch)
treeeb0eebcbc70e392348e4966a41d17d0896903070
parentaf2de536d35c9a450b12d9c9f207898e9d864951 (diff)
parentbd75f9e61375c7632bb55b0d49b470ecd94e8ec7 (diff)
downloadphp-git-da5e09ad0389f53cdc78591442a3df1ff54c6ff0.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
-rw-r--r--.gdbinit41
-rw-r--r--NEWS4
-rw-r--r--ext/mysqli/tests/bug69899.phpt38
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c5
4 files changed, 71 insertions, 17 deletions
diff --git a/.gdbinit b/.gdbinit
index 9b042794cc..09faf936da 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -29,24 +29,35 @@ document ____executor_globals
end
define print_cvs
- ____executor_globals
- set $p = $eg.current_execute_data.CVs
- set $c = $eg.current_execute_data.op_array.last_var
- set $v = $eg.current_execute_data.op_array.vars
- set $i = 0
+ if $argc == 0
+ ____executor_globals
+ set $cv_ex_ptr = $eg.current_execute_data
+ else
+ set $cv_ex_ptr = (zend_execute_data *)$arg0
+ end
+ set $cv_count = $cv_ex_ptr.func.op_array.last_var
+ set $cv = $cv_ex_ptr.func.op_array.vars
+ set $cv_idx = 0
+ set $callFrameSize = (sizeof(zend_execute_data) + sizeof(zval) - 1) / sizeof(zval)
- printf "Compiled variables count: %d\n", $c
- while $i < $c
- printf "%d = %s\n", $i, $v[$i].name
- if $p[$i] != 0
- printzv *$p[$i]
- else
- printf "*uninitialized*\n"
- end
- set $i = $i + 1
+ printf "Compiled variables count: %d\n\n", $cv_count
+ while $cv_idx < $cv_count
+ printf "[%d] '%s'\n", $cv_idx, $cv[$cv_idx].val
+ set $zvalue = ((zval *) $cv_ex_ptr) + $callFrameSize + $cv_idx
+ printzv $zvalue
+ set $cv_idx = $cv_idx + 1
end
end
+document print_cvs
+ Prints the compiled variables and their values.
+ If a zend_execute_data pointer is set this will print the compiled
+ variables of that scope. If no parameter is used it will use
+ current_execute_data for scope.
+
+ usage: print_cvs [zend_execute_data *]
+end
+
define dump_bt
set $ex = $arg0
while $ex
@@ -563,7 +574,7 @@ end
document print_zstr
print the length and contents of a zend string
- usage: print_zstr [ptr]
+ usage: print_zstr <ptr>
end
define zbacktrace
diff --git a/NEWS b/NEWS
index dee7ca9513..05e3d9e774 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ PHP NEWS
- FCGI:
. Fixed bug #73904 (php-cgi fails to load -c specified php.ini file). (Anatol)
+- 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)
. Fixed bug #73692 (Compile ext/openssl with openssl 1.1.0 on Win). (Anatol)
diff --git a/ext/mysqli/tests/bug69899.phpt b/ext/mysqli/tests/bug69899.phpt
new file mode 100644
index 0000000000..177b5e3dce
--- /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 c805e6f111..256bbe4d47 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -2032,8 +2032,9 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s)
stmt->state = MYSQLND_STMT_PREPARED;
}
- /* Line is free! */
- SET_CONNECTION_STATE(&conn->state, CONN_READY);
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_QUIT_SENT) {
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
+ }
DBG_RETURN(PASS);
}