andrey                                   Tue, 17 Aug 2010 18:08:25 +0000

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

Log:
Fix for Bug #52613 crash in mysqlnd

Bug: http://bugs.php.net/52613 (Assigned) crash in mysqlnd
      
Changed paths:
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c   2010-08-17 
18:07:19 UTC (rev 302397)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c   2010-08-17 
18:08:25 UTC (rev 302398)
@@ -91,7 +91,11 @@
 void mysqlnd_palloc_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, 
zend_bool * copy_ctor_called TSRMLS_DC)
 {
        DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
-
+       if (!zv || !*zv) {
+               *copy_ctor_called = FALSE;
+               DBG_ERR_FMT("zv was NULL");
+               DBG_VOID_RETURN;
+       }
        /*
          This zval is not from the cache block.
          Thus the refcount is -1 than of a zval from the cache,
@@ -158,17 +162,16 @@
                for (i = 0; i < result->field_count; i++) {
                        
mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, 
&copy_ctor_called TSRMLS_CC);
                        if (copy_ctor_called) {
-                               ctor_called_count++;
+                               ++ctor_called_count;
                        }
                }
                DBG_INF_FMT("copy_ctor_called_count=%u", ctor_called_count);
                /* By using value3 macros we hold a mutex only once, there is 
no value2 */
-               MYSQLND_INC_CONN_STATISTIC_W_VALUE3(global_stats,
+               MYSQLND_INC_CONN_STATISTIC_W_VALUE2(global_stats,
                                                                                
        STAT_COPY_ON_WRITE_PERFORMED,
                                                                                
        ctor_called_count,
                                                                                
        STAT_COPY_ON_WRITE_SAVED,
-                                                                               
        result->field_count - ctor_called_count,
-                                                                               
        STAT_COPY_ON_WRITE_PERFORMED, 0);
+                                                                               
        result->field_count - ctor_called_count);

                /* Free last row's zvals */
                mnd_efree(unbuf->last_row_data);
@@ -199,6 +202,8 @@

        DBG_INF("Freeing data & row_buffer");
        if (set->data) {
+               unsigned int copy_on_write_performed = 0;
+               unsigned int copy_on_write_saved = 0;

                DBG_INF_FMT("before: real_usage=%lu  usage=%lu", 
zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
                for (row = set->row_count - 1; row >= 0; row--) {
@@ -206,16 +211,21 @@
                        MYSQLND_MEMORY_POOL_CHUNK *current_buffer = 
set->row_buffers[row];
                        int col;

-                       for (col = field_count - 1; col >= 0; --col) {
-                               zend_bool copy_ctor_called;
-                               if (current_row == NULL || current_row[0] == 
NULL) {
-                                       break;/* row that was never initialized 
*/
-                               }
-                               
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, 
&copy_ctor_called TSRMLS_CC);
+                       if (current_row != NULL) {
+                               for (col = field_count - 1; col >= 0; --col) {
+                                       if (current_row[col]) {
+                                               zend_bool copy_ctor_called;
+                                               
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, 
&copy_ctor_called TSRMLS_CC);
 #if MYSQLND_DEBUG_MEMORY
-                               DBG_INF_FMT("Copy_ctor_called=%u", 
copy_ctor_called);
+                                               
DBG_INF_FMT("Copy_ctor_called=%u", copy_ctor_called);
 #endif
-                               MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? 
STAT_COPY_ON_WRITE_PERFORMED: STAT_COPY_ON_WRITE_SAVED);
+                                               if (copy_ctor_called) {
+                                                       
++copy_on_write_performed;
+                                               } else {
+                                                       ++copy_on_write_saved;
+                                               }
+                                       }
+                               }
                        }
 #if MYSQLND_DEBUG_MEMORY
                        DBG_INF("Freeing current_row & current_buffer");
@@ -223,6 +233,8 @@
                        current_buffer->free_chunk(current_buffer TSRMLS_CC);
                }

+               
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, 
copy_on_write_performed,
+                                                                               
          STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved);
                mnd_pefree(set->data, set->persistent);
                set->data = NULL;
        }

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c      2010-08-17 18:07:19 UTC 
(rev 302397)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c      2010-08-17 18:08:25 UTC 
(rev 302398)
@@ -91,7 +91,11 @@
 void mysqlnd_palloc_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, 
zend_bool * copy_ctor_called TSRMLS_DC)
 {
        DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
-
+       if (!zv || !*zv) {
+               *copy_ctor_called = FALSE;
+               DBG_ERR_FMT("zv was NULL");
+               DBG_VOID_RETURN;
+       }
        /*
          This zval is not from the cache block.
          Thus the refcount is -1 than of a zval from the cache,
@@ -158,17 +162,16 @@
                for (i = 0; i < result->field_count; i++) {
                        
mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, 
&copy_ctor_called TSRMLS_CC);
                        if (copy_ctor_called) {
-                               ctor_called_count++;
+                               ++ctor_called_count;
                        }
                }
                DBG_INF_FMT("copy_ctor_called_count=%u", ctor_called_count);
                /* By using value3 macros we hold a mutex only once, there is 
no value2 */
-               MYSQLND_INC_CONN_STATISTIC_W_VALUE3(global_stats,
+               MYSQLND_INC_CONN_STATISTIC_W_VALUE2(global_stats,
                                                                                
        STAT_COPY_ON_WRITE_PERFORMED,
                                                                                
        ctor_called_count,
                                                                                
        STAT_COPY_ON_WRITE_SAVED,
-                                                                               
        result->field_count - ctor_called_count,
-                                                                               
        STAT_COPY_ON_WRITE_PERFORMED, 0);
+                                                                               
        result->field_count - ctor_called_count);

                /* Free last row's zvals */
                mnd_efree(unbuf->last_row_data);
@@ -199,6 +202,8 @@

        DBG_INF("Freeing data & row_buffer");
        if (set->data) {
+               unsigned int copy_on_write_performed = 0;
+               unsigned int copy_on_write_saved = 0;

                DBG_INF_FMT("before: real_usage=%lu  usage=%lu", 
zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
                for (row = set->row_count - 1; row >= 0; row--) {
@@ -206,16 +211,21 @@
                        MYSQLND_MEMORY_POOL_CHUNK *current_buffer = 
set->row_buffers[row];
                        int col;

-                       for (col = field_count - 1; col >= 0; --col) {
-                               zend_bool copy_ctor_called;
-                               if (current_row == NULL || current_row[0] == 
NULL) {
-                                       break;/* row that was never initialized 
*/
-                               }
-                               
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, 
&copy_ctor_called TSRMLS_CC);
+                       if (current_row != NULL) {
+                               for (col = field_count - 1; col >= 0; --col) {
+                                       if (current_row[col]) {
+                                               zend_bool copy_ctor_called;
+                                               
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, 
&copy_ctor_called TSRMLS_CC);
 #if MYSQLND_DEBUG_MEMORY
-                               DBG_INF_FMT("Copy_ctor_called=%u", 
copy_ctor_called);
+                                               
DBG_INF_FMT("Copy_ctor_called=%u", copy_ctor_called);
 #endif
-                               MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? 
STAT_COPY_ON_WRITE_PERFORMED: STAT_COPY_ON_WRITE_SAVED);
+                                               if (copy_ctor_called) {
+                                                       
++copy_on_write_performed;
+                                               } else {
+                                                       ++copy_on_write_saved;
+                                               }
+                                       }
+                               }
                        }
 #if MYSQLND_DEBUG_MEMORY
                        DBG_INF("Freeing current_row & current_buffer");
@@ -223,6 +233,8 @@
                        current_buffer->free_chunk(current_buffer TSRMLS_CC);
                }

+               
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, 
copy_on_write_performed,
+                                                                               
          STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved);
                mnd_pefree(set->data, set->persistent);
                set->data = NULL;
        }

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

Reply via email to