andrey                                   Wed, 29 Sep 2010 13:18:07 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=303855

Log:
Fix a problem that leads to leaks in plugins that
use stmt local data - no free is called for statements
that are over-prepared

Changed paths:
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c       2010-09-29 
11:40:57 UTC (rev 303854)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c       2010-09-29 
13:18:07 UTC (rev 303855)
@@ -433,13 +433,19 @@
        }

        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");

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c  2010-09-29 11:40:57 UTC (rev 
303854)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c  2010-09-29 13:18:07 UTC (rev 
303855)
@@ -433,13 +433,19 @@
        }

        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");

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to