]> granicus.if.org Git - php/commitdiff
Fixed bug #77599 (Unbuffered queries; native prepared statements memory leak)
authorDmitry Stogov <dmitry@zend.com>
Tue, 12 Feb 2019 07:55:05 +0000 (10:55 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 12 Feb 2019 07:55:05 +0000 (10:55 +0300)
NEWS
ext/mysqlnd/mysqlnd_ps.c

diff --git a/NEWS b/NEWS
index 8f3e10e09a7ba0248f61ae4fabea9b38944432fc..a1fb54f0df546ece4f5cb4aba273d1af29408411 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,10 @@ PHP                                                                        NEWS
   . Fixed bug #77514 (mb_ereg_replace() with trailing backslash adds null byte).
     (Nikita)
 
+- MySQLnd:
+  . Fixed bug #77599 (Unbuffered queries; native prepared statements memory
+    leak). (Dmitry)
+
 - OpenSSL:
   . Fixed bug #77390 (feof might hang on TLS streams in case of fragmented TLS
     records). (Abyl Valg, Jakub Zelenka)
index f3fab43f0c07584a4ed3cdbab90d1a8513cf3a80..b2017b9127f59f80e9408fc4454104985ee69ca4 100644 (file)
@@ -851,6 +851,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi
        MYSQLND_PACKET_ROW * row_packet;
        MYSQLND_CONN_DATA * conn = result->conn;
        const MYSQLND_RES_METADATA * const meta = result->meta;
+       void *checkpoint;
 
        DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered");
 
@@ -873,6 +874,9 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi
        /* Let the row packet fill our buffer and skip additional malloc + memcpy */
        row_packet->skip_extraction = stmt && stmt->result_bind? FALSE:TRUE;
 
+       checkpoint = result->memory_pool->checkpoint;
+       mysqlnd_mempool_save_state(result->memory_pool);
+
        /*
          If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to
          result->unbuf->m.free_last_data() before it. The function returns always true.
@@ -895,6 +899,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi
                                                                        conn->options->int_and_float_native,
                                                                        conn->stats))
                        {
+                               mysqlnd_mempool_restore_state(result->memory_pool);
+                               result->memory_pool->checkpoint = checkpoint;
                                DBG_RETURN(FAIL);
                        }
 
@@ -965,6 +971,9 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi
                }
        }
 
+       mysqlnd_mempool_restore_state(result->memory_pool);
+       result->memory_pool->checkpoint = checkpoint;
+
        DBG_INF_FMT("ret=%s fetched_anything=%u", ret == PASS? "PASS":"FAIL", *fetched_anything);
        DBG_RETURN(ret);
 }