]> granicus.if.org Git - php/commitdiff
Fix bug #78525
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 12 Sep 2019 11:17:27 +0000 (13:17 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 13 Sep 2019 12:37:03 +0000 (14:37 +0200)
When calling free_result_buffers(), also free field metadata and
restore the mempool state to what it was before any allocations
have been made. Remove the mempool save/restore logic for the
inner result set as this is now handled on a higher level.

NEWS
ext/mysqlnd/mysqlnd_block_alloc.c
ext/mysqlnd/mysqlnd_result.c

diff --git a/NEWS b/NEWS
index 0e2a2c6482a6bf4ce932815db42afc5e1a894665..5eda3023290ae0b610553fa81607032d94a8534f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,9 +3,13 @@ PHP                                                                        NEWS
 ?? ??? ????, PHP 7.3.11
 
 - Exif :
-       .Fixed bug #78442 ('Illegal component' on exif_read_data since PHP7)
+  Fixed bug #78442 ('Illegal component' on exif_read_data since PHP7)
        (Kalle)
 
+- Mysqlnd:
+  . Fixed bug #78525 (Memory leak in pdo when reusing native prepared
+    statements). (Nikita)
+
 12 Sep 2019, PHP 7.3.10RC1
 
 - Core:
index 10f6bd3b6db5dbaf0be8bc61bd8e8859e2739554..cba7530c8db35015b8eafbd9d5ddbe34efcb6e48 100644 (file)
@@ -200,6 +200,9 @@ PHPAPI void
 mysqlnd_mempool_restore_state(MYSQLND_MEMORY_POOL * pool)
 {
        DBG_ENTER("mysqlnd_mempool_restore_state");
+#if ZEND_DEBUG
+       ZEND_ASSERT(pool->checkpoint);
+#endif
        if (pool->checkpoint) {
                mysqlnd_arena_release(&pool->arena, pool->checkpoint);
                pool->last = NULL;
index 06a7793c9acdc4f80cfff39808febd84c8ad3cf9..783fd2cec10d153f8ef0782a4cc0a0ba400da2d6 100644 (file)
@@ -190,8 +190,6 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED *
                result->row_packet = NULL;
        }
 
-       mysqlnd_mempool_restore_state(result->result_set_memory_pool);
-
        DBG_VOID_RETURN;
 }
 /* }}} */
@@ -261,8 +259,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
                set->row_buffers = NULL;
        }
 
-       mysqlnd_mempool_restore_state(set->result_set_memory_pool);
-
        DBG_VOID_RETURN;
 }
 /* }}} */
@@ -275,6 +271,12 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result)
        DBG_ENTER("mysqlnd_res::free_result_buffers");
        DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->stored_data? "buffered":"unknown"));
 
+       if (result->meta) {
+               ZEND_ASSERT(zend_arena_contains(result->memory_pool->arena, result->meta));
+               result->meta->m->free_metadata(result->meta);
+               result->meta = NULL;
+       }
+
        if (result->unbuf) {
                result->unbuf->m.free_result(result->unbuf, result->conn? result->conn->stats : NULL);
                result->unbuf = NULL;
@@ -283,6 +285,9 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result)
                result->stored_data = NULL;
        }
 
+       mysqlnd_mempool_restore_state(result->memory_pool);
+       mysqlnd_mempool_save_state(result->memory_pool);
+
        DBG_VOID_RETURN;
 }
 /* }}} */
@@ -294,12 +299,6 @@ void MYSQLND_METHOD(mysqlnd_res, free_result_contents_internal)(MYSQLND_RES * re
 {
        DBG_ENTER("mysqlnd_res::free_result_contents_internal");
 
-       if (result->meta) {
-               ZEND_ASSERT(zend_arena_contains(result->memory_pool->arena, result->meta));
-               result->meta->m->free_metadata(result->meta);
-               result->meta = NULL;
-       }
-
        result->m.free_result_buffers(result);
 
        DBG_VOID_RETURN;
@@ -1926,6 +1925,8 @@ mysqlnd_result_init(const unsigned int field_count)
        ret->field_count        = field_count;
        ret->m = *mysqlnd_result_get_methods();
 
+       mysqlnd_mempool_save_state(pool);
+
        DBG_RETURN(ret);
 }
 /* }}} */
@@ -1941,7 +1942,6 @@ mysqlnd_result_unbuffered_init(MYSQLND_RES *result, const unsigned int field_cou
 
        DBG_ENTER("mysqlnd_result_unbuffered_init");
 
-       mysqlnd_mempool_save_state(pool);
        ret = pool->get_chunk(pool, alloc_size);
        memset(ret, 0, alloc_size);
 
@@ -1976,12 +1976,10 @@ mysqlnd_result_buffered_zval_init(MYSQLND_RES * result, const unsigned int field
 
        DBG_ENTER("mysqlnd_result_buffered_zval_init");
 
-       mysqlnd_mempool_save_state(pool);
        ret = pool->get_chunk(pool, alloc_size);
        memset(ret, 0, alloc_size);
 
        if (FAIL == mysqlnd_error_info_init(&ret->error_info, 0)) {
-               mysqlnd_mempool_restore_state(pool);
                DBG_RETURN(NULL);
        }
 
@@ -2019,12 +2017,10 @@ mysqlnd_result_buffered_c_init(MYSQLND_RES * result, const unsigned int field_co
 
        DBG_ENTER("mysqlnd_result_buffered_c_init");
 
-       mysqlnd_mempool_save_state(pool);
        ret = pool->get_chunk(pool, alloc_size);
        memset(ret, 0, alloc_size);
 
        if (FAIL == mysqlnd_error_info_init(&ret->error_info, 0)) {
-               mysqlnd_mempool_restore_state(pool);
                DBG_RETURN(NULL);
        }