]> granicus.if.org Git - php/commitdiff
Fixed bug #77308 (Unbuffered queries memory leak)
authorDmitry Stogov <dmitry@zend.com>
Mon, 14 Jan 2019 10:59:30 +0000 (13:59 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 14 Jan 2019 10:59:30 +0000 (13:59 +0300)
NEWS
ext/mysqlnd/mysqlnd_result.c

diff --git a/NEWS b/NEWS
index e65172c9193aeab00be76d3ecdae031f09722326..5b037dd8e5582cd0d668d260d2feb8d304cd4037 100644 (file)
--- 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)
 
index 38fe1166860d85c78ced37260fab1f81ab8af86d..201e314f7d51d6a22c55132dd48cc9014f324bf7 100644 (file)
@@ -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);
 }