Blob Blame History Raw
From 9137acc7ecdf1542fe6fda5056a0273359682735 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@php.net>
Date: Thu, 27 Feb 2014 08:45:16 +0100
Subject: [PATCH] Fixed Bug #66762 Segfault in mysqli_stmt::bind_result() when
 link closed

Each new mysqli_stmt now increase the refcount of the link object.
So the link is really destroy after all statements.

Only implemented with libmysqlclient, as mysqlnd already implement
this internally.

So, libmysqlclient and mysqlnd have the same behavior.
---
 ext/mysqli/mysqli.c             | 9 ++++++++-
 ext/mysqli/mysqli_api.c         | 8 ++++++++
 ext/mysqli/php_mysqli_structs.h | 4 ++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 4e4ed5b..cbeb183 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -176,8 +176,11 @@ void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
 	php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
 	/* Clean output bind */
 	php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
-#endif
 
+	if (stmt->link_handle) {
+	    zend_objects_store_del_ref_by_handle(stmt->link_handle TSRMLS_CC);
+	}
+#endif
 	if (stmt->query) {
 		efree(stmt->query);
 	}
@@ -1055,6 +1058,10 @@ PHP_FUNCTION(mysqli_stmt_construct)
 		efree(stmt);
 		RETURN_FALSE;
 	}
+#ifndef MYSQLI_USE_MYSQLND
+	stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+	zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
 
 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 	mysqli_resource->ptr = (void *)stmt;
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 1dbff87..0b28a43 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -1840,6 +1840,10 @@ PHP_FUNCTION(mysqli_prepare)
 		efree(stmt);
 		RETURN_FALSE;
 	}
+#ifndef MYSQLI_USE_MYSQLND
+	stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+	zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
 
 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 	mysqli_resource->ptr = (void *)stmt;
@@ -2368,6 +2372,10 @@ PHP_FUNCTION(mysqli_stmt_init)
 		efree(stmt);
 		RETURN_FALSE;
 	}
+#ifndef MYSQLI_USE_MYSQLND
+	stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+	zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
 
 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h
index d652592..d2fb34b 100644
--- a/ext/mysqli/php_mysqli_structs.h
+++ b/ext/mysqli/php_mysqli_structs.h
@@ -116,6 +116,10 @@ typedef struct {
 	BIND_BUFFER	param;
 	BIND_BUFFER	result;
 	char		*query;
+#ifndef MYSQLI_USE_MYSQLND
+	/* used to manage refcount with libmysql (already implement in mysqlnd) */
+	zend_object_handle link_handle;
+#endif
 } MY_STMT;
 
 typedef struct {
-- 
2.1.4

From 816a5d207270556aa5a9d74cdd8629d1b06cc350 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@php.net>
Date: Thu, 27 Feb 2014 08:48:01 +0100
Subject: [PATCH] test for bug #66762

---
 ext/mysqli/tests/bug66762.phpt | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 ext/mysqli/tests/bug66762.phpt

diff --git a/ext/mysqli/tests/bug66762.phpt b/ext/mysqli/tests/bug66762.phpt
new file mode 100644
index 0000000..2b8a92c
--- /dev/null
+++ b/ext/mysqli/tests/bug66762.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #66762 	mysqli@libmysql segfault in mysqli_stmt::bind_result() when link closed
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+	require_once("connect.inc");
+
+	$mysqli = new mysqli($host, $user, $passwd, $db);
+
+	$read_stmt = $mysqli->prepare("SELECT 1");
+
+	var_dump($read_stmt->bind_result($data));
+
+	unset($mysqli);
+	var_dump($read_stmt->bind_result($data));
+	
+?>
+done!
+--EXPECT--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
-- 
2.1.4