]> granicus.if.org Git - php/commitdiff
Fixed bug #77773
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 22 Mar 2019 12:07:00 +0000 (13:07 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 22 Mar 2019 12:07:00 +0000 (13:07 +0100)
NEWS
ext/mysqlnd/mysqlnd_result.c

diff --git a/NEWS b/NEWS
index 499a43581d05bdd25b383cf1a6802b8b5b3f3913..30a0b19ea82ee0937b9930304491ae5b9fe8235a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? ????, PHP 7.3.5
 
+- MySQLi:
+  . Fixed bug #77773 (Unbuffered queries leak memory - MySQLi / mysqlnd).
+    (Nikita)
+
 - Reflection:
   . Fixed bug #77772 (ReflectionClass::getMethods(null) doesn't work). (Nikita)
 
index 5e3b86e12d9b621df2f29a0aa73d63d7b3d9f95e..f0852af360b16406082f32e38089011da5c0a9df 100644 (file)
@@ -781,6 +781,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
        MYSQLND_PACKET_ROW      *row_packet = result->unbuf->row_packet;
        const MYSQLND_RES_METADATA * const meta = result->meta;
        MYSQLND_CONN_DATA * const conn = result->conn;
+       void *checkpoint;
 
        DBG_ENTER("mysqlnd_result_unbuffered::fetch_row");
 
@@ -800,6 +801,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
        /* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */
        row_packet->skip_extraction = row? FALSE:TRUE;
 
+       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.
@@ -824,6 +828,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
                                                                                                                           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);
                        }
                        {
@@ -894,6 +900,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
                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);
 }