Hi,

Attached is a proposed fix for http://bugs.php.net/bug.php?id=45392 for
PHP_5_3. I don't know output buffering part very well, and I'm not
completely sure about this fix, so please review it.

The patch changes behavior of output buffering a bit. In case of fatal
error all output buffers opened by ob_start() with zero (or omitted)
chunk_size argument are discarded. The fix brakes two tests:

Test session_module_name() function : variation
[ext/session/tests/session_module_name_variation3.phpt]
Test session_set_save_handler() function : error functionality
[ext/session/tests/session_set_save_handler_error3.phpt]

We need to make a decision about #45392.

1) Fix it with proposed (or similar) patch

2) Make it bogus because any fix requires output buffering behavior change

Thanks. Dmitry.
Index: NEWS
===================================================================
RCS file: /repository/php-src/NEWS,v
retrieving revision 1.2027.2.547.2.965.2.305
diff -u -p -d -r1.2027.2.547.2.965.2.305 NEWS
--- NEWS        1 Sep 2008 20:51:57 -0000       1.2027.2.547.2.965.2.305
+++ NEWS        2 Sep 2008 08:31:03 -0000
@@ -1,6 +1,9 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 200?, PHP 5.3.0 Alpha 3
+- Fixed bug #45392 (ob_start()/ob_end_clean() and memory_limit. In case of
+  fatal error active output buffers with zero chunk_size (the default value of
+  the second argument to ob_start()) are discarded). (Dmitry)
 
 02 Sep 2008, PHP 5.3.0 Alpha 2
 - Removed special treatment of "/tmp" in sessions for open_basedir.
Index: main/main.c
===================================================================
RCS file: /repository/php-src/main/main.c,v
retrieving revision 1.640.2.23.2.57.2.32
diff -u -p -d -r1.640.2.23.2.57.2.32 main.c
--- main/main.c 26 Aug 2008 23:26:07 -0000      1.640.2.23.2.57.2.32
+++ main/main.c 2 Sep 2008 08:31:03 -0000
@@ -852,6 +852,19 @@ static void php_error_cb(int type, const
                }
        }
 
+    if (!SG(request_info).headers_only) {
+               /* Discard output buffers with zero chunk_size on fatal error */
+               switch (type) {
+                       case E_CORE_ERROR:
+                       case E_ERROR:
+                       case E_RECOVERABLE_ERROR:
+                       case E_PARSE:
+                       case E_COMPILE_ERROR:
+                       case E_USER_ERROR:
+                               php_discard_ob_buffers(TSRMLS_C);
+               }
+       }
+
        /* display/log the error if necessary */
        if (display && (EG(error_reporting) & type || (type & E_CORE))
                && (PG(log_errors) || PG(display_errors) || 
(!module_initialized))) {
Index: main/output.c
===================================================================
RCS file: /repository/php-src/main/output.c,v
retrieving revision 1.167.2.3.2.4.2.9
diff -u -p -d -r1.167.2.3.2.4.2.9 output.c
--- main/output.c       18 Aug 2008 07:46:31 -0000      1.167.2.3.2.4.2.9
+++ main/output.c       2 Sep 2008 08:31:03 -0000
@@ -341,6 +341,45 @@ PHPAPI void php_end_ob_buffers(zend_bool
 }
 /* }}} */
 
+typedef struct _php_ob_calc_discard_rec {
+       int count;
+       int last;
+} php_ob_calc_discard_rec;
+
+/* {{{ php_ob_list_each
+ */
+static int php_ob_calc_discard(php_ob_buffer *ob_buffer, 
php_ob_calc_discard_rec *discard) 
+{
+       discard->count++;
+       if (!ob_buffer->chunk_size) {
+               discard->last = discard->count;
+       }
+       return 0;
+}
+/* }}} */
+
+
+/* {{{ php_discard_ob_buffers
+ * Discard output buffers with zero chunk_size */
+PHPAPI void php_discard_ob_buffers(TSRMLS_D)
+{
+       if (OG(ob_nesting_level)) {
+               php_ob_calc_discard_rec discard;
+
+               discard.count = 0;
+               discard.last = 0;
+               php_ob_calc_discard(&OG(active_ob_buffer), &discard);
+               if (OG(ob_nesting_level)>1) {
+                       zend_stack_apply_with_argument(&OG(ob_buffers), 
ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) php_ob_calc_discard, 
&discard);
+               }
+               while (discard.last) {
+                       php_end_ob_buffer(OG(active_ob_buffer).chunk_size != 0, 
0 TSRMLS_CC);
+                       discard.last--;
+               }
+       }
+}
+/* }}} */
+
 /* {{{ php_start_implicit_flush
  */
 PHPAPI void php_start_implicit_flush(TSRMLS_D)
Index: main/php_output.h
===================================================================
RCS file: /repository/php-src/main/php_output.h,v
retrieving revision 1.53.2.1.2.1.2.1
diff -u -p -d -r1.53.2.1.2.1.2.1 php_output.h
--- main/php_output.h   31 Dec 2007 07:17:17 -0000      1.53.2.1.2.1.2.1
+++ main/php_output.h   2 Sep 2008 08:31:03 -0000
@@ -37,6 +37,7 @@ PHPAPI int php_start_ob_buffer(zval *out
 PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint 
chunk_size, zend_bool erase TSRMLS_DC);
 PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush 
TSRMLS_DC);
 PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC);
+PHPAPI void php_discard_ob_buffers(TSRMLS_D);
 PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC);
 PHPAPI int php_ob_get_length(zval *p TSRMLS_DC);
 PHPAPI void php_start_implicit_flush(TSRMLS_D);

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to