From 1a306cc9a1679a758c859731a78429429830a439 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 14 Jan 2019 13:59:30 +0300 Subject: [PATCH] Fixed bug #77308 (Unbuffered queries memory leak) --- NEWS | 1 + ext/mysqlnd/mysqlnd_result.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/NEWS b/NEWS index e65172c919..5b037dd8e5 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,7 @@ PHP NEWS (64796c6e69 at gmail dot com) - MySQLnd: + . Fixed bug #77308 (Unbuffered queries memory leak). (Dmitry) . Fixed bug #75684 (In mysqlnd_ext_plugin.h the plugin methods family has no external visibility). (Anatol) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 38fe116686..201e314f7d 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -651,6 +651,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet; MYSQLND_RES_METADATA * const meta = result->meta; MYSQLND_CONN_DATA * const conn = result->conn; + void *checkpoint; DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c"); @@ -670,6 +671,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi /* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */ row_packet->skip_extraction = FALSE; + checkpoint = result->memory_pool->checkpoint; + mysqlnd_mempool_save_state(result->memory_pool); + /* If we skip rows (row == NULL) we have to result->m.unbuffered_free_last_data() before it. The function returns always true. @@ -694,6 +698,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi conn->options->int_and_float_native, conn->stats); if (PASS != rc) { + mysqlnd_mempool_restore_state(result->memory_pool); + result->memory_pool->checkpoint = checkpoint; DBG_RETURN(FAIL); } { @@ -757,6 +763,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi result->unbuf->m.free_last_data(result->unbuf, conn->stats); } + mysqlnd_mempool_restore_state(result->memory_pool); + result->memory_pool->checkpoint = checkpoint; + DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything); DBG_RETURN(PASS); } -- 2.40.0