summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2010-09-29 13:18:07 +0000
committerAndrey Hristov <andrey@php.net>2010-09-29 13:18:07 +0000
commit3113744c5794f154412145efb39352e25849081c (patch)
tree93ec0adb9d8ef67840b34cf6117baa187fabaf6c
parent517fd63c328b90ec0501cb9a10bc7f4398c8cb1d (diff)
downloadphp-git-3113744c5794f154412145efb39352e25849081c.tar.gz
Fix a problem that leads to leaks in plugins that
use stmt local data - no free is called for statements that are over-prepared
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index c06d1b4882..70bcef9e38 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -433,13 +433,19 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
}
if (stmt_to_prepare != stmt) {
- /* Free old buffers, binding and resources on server */
- s->m->net_close(s, TRUE TSRMLS_CC);
-
- memcpy(stmt, stmt_to_prepare, sizeof(MYSQLND_STMT_DATA));
-
- /* Now we will have a clean new statement object */
- mnd_pefree(stmt_to_prepare, stmt_to_prepare->persistent);
+ /* swap */
+ size_t real_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
+ char * tmp_swap = mnd_malloc(real_size);
+ memcpy(tmp_swap, s, real_size);
+ memcpy(s, s_to_prepare, real_size);
+ memcpy(s_to_prepare, tmp_swap, real_size);
+ mnd_free(tmp_swap);
+ {
+ MYSQLND_STMT_DATA * tmp_swap_data = stmt_to_prepare;
+ stmt_to_prepare = stmt;
+ stmt = tmp_swap_data;
+ }
+ s_to_prepare->m->dtor(s_to_prepare, TRUE TSRMLS_CC);
}
stmt->state = MYSQLND_STMT_PREPARED;
DBG_INF("PASS");