- fix buffer size alignment

- avoid memory overflow #if MEMORY_LIMIT
This commit is contained in:
Michael Wallner 2006-11-13 14:05:03 +00:00
parent d3c4b8ca80
commit d96f225a15
2 changed files with 46 additions and 28 deletions

View file

@ -52,7 +52,13 @@ static HashTable php_output_handler_reverse_conflicts;
static inline int php_output_lock_error(int op TSRMLS_DC); static inline int php_output_lock_error(int op TSRMLS_DC);
static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC); static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC);
static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags); #if MEMORY_LIMIT
#define php_output_handler_init(n, cs, f) php_output_handler_init_ex((n), (cs), (f) TSRMLS_CC)
static inline php_output_handler *php_output_handler_init_ex(zval *name, size_t chunk_size, int flags TSRMLS_DC);
#else
#define php_output_handler_init php_output_handler_init_ex
static inline php_output_handler *php_output_handler_init_ex(zval *name, size_t chunk_size, int flags);
#endif
static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context); static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context);
static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC); static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC);
static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry); static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry);
@ -849,13 +855,28 @@ static inline void php_output_context_dtor(php_output_context *context)
/* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) /* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags)
Allocates and initializes a php_output_handler structure */ Allocates and initializes a php_output_handler structure */
static inline php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags) #if MEMORY_LIMIT
static inline php_output_handler *php_output_handler_init_ex(zval *name, size_t chunk_size, int flags TSRMLS_DC)
#else
static inline php_output_handler *php_output_handler_init_ex(zval *name, size_t chunk_size, int flags)
#endif
{ {
php_output_handler *handler; php_output_handler *handler;
#if MEMORY_LIMIT
size_t mem_limit;
#endif
handler = ecalloc(1, sizeof(php_output_handler)); handler = ecalloc(1, sizeof(php_output_handler));
ZVAL_ADDREF(name); ZVAL_ADDREF(name);
handler->name = name; handler->name = name;
#if MEMORY_LIMIT
mem_limit = (PG(memory_limit) - zend_memory_usage(1 TSRMLS_CC)) / 2;
if (!chunk_size || chunk_size > mem_limit) {
handler->size = mem_limit;
chunk_size = 0;
} else
#endif
handler->size = chunk_size; handler->size = chunk_size;
handler->flags = flags; handler->flags = flags;
handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size); handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size);
@ -874,14 +895,13 @@ static inline int php_output_handler_append(php_output_handler *handler, const p
/* store it away */ /* store it away */
if ((handler->buffer.size - handler->buffer.used) <= buf->used) { if ((handler->buffer.size - handler->buffer.used) <= buf->used) {
size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size); size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size);
size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used + 1 - (handler->buffer.size - handler->buffer.used)); size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used - (handler->buffer.size - handler->buffer.used));
size_t grow_max = MAX(grow_int, grow_buf); size_t grow_max = MAX(grow_int, grow_buf);
handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size += grow_max); handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size += grow_max);
} }
memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used); memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used);
handler->buffer.used += buf->used; handler->buffer.used += buf->used;
handler->buffer.data[handler->buffer.used] = '\0';
/* chunked buffering */ /* chunked buffering */
if (handler->size && (handler->buffer.used >= handler->size)) { if (handler->size && (handler->buffer.used >= handler->size)) {
@ -898,6 +918,7 @@ static inline int php_output_handler_append(php_output_handler *handler, const p
static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context) static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
{ {
php_output_handler_status_t status; php_output_handler_status_t status;
int original_op = context->op;
PHP_OUTPUT_TSRMLS(context); PHP_OUTPUT_TSRMLS(context);
#if PHP_OUTPUT_DEBUG #if PHP_OUTPUT_DEBUG
@ -1017,6 +1038,7 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
break; break;
} }
context->op = original_op;
return status; return status;
} }
/* }}} */ /* }}} */
@ -1057,29 +1079,27 @@ static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
context.out.used = len; context.out.used = len;
} }
if (context.out.data) { if (context.out.data && context.out.used) {
if (context.out.used) {
#if PHP_OUTPUT_DEBUG #if PHP_OUTPUT_DEBUG
fprintf(stderr, "::: sapi_write('%s', %zu)\n", context.out.data, context.out.used); fprintf(stderr, "::: sapi_write('%s', %zu)\n", context.out.data, context.out.used);
#endif #endif
if (!SG(headers_sent) && php_header(TSRMLS_C)) { if (!SG(headers_sent) && php_header(TSRMLS_C)) {
if (zend_is_compiling(TSRMLS_C)) { if (zend_is_compiling(TSRMLS_C)) {
OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C); OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C);
OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C); OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C);
} else if (zend_is_executing(TSRMLS_C)) { } else if (zend_is_executing(TSRMLS_C)) {
OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C); OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C);
OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C); OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C);
} }
#if PHP_OUTPUT_DEBUG #if PHP_OUTPUT_DEBUG
fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno)); fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno));
#endif #endif
}
sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC);
if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) {
sapi_flush(TSRMLS_C);
}
OG(flags) |= PHP_OUTPUT_SENT;
} }
sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC);
if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) {
sapi_flush(TSRMLS_C);
}
OG(flags) |= PHP_OUTPUT_SENT;
} }
php_output_context_dtor(&context); php_output_context_dtor(&context);
} }
@ -1089,7 +1109,7 @@ static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
Operation callback for the stack apply function */ Operation callback for the stack apply function */
static int php_output_stack_apply_op(void *h, void *c) static int php_output_stack_apply_op(void *h, void *c)
{ {
int was_disabled, op; int was_disabled;
php_output_handler_status_t status; php_output_handler_status_t status;
php_output_handler *handler = *(php_output_handler **) h; php_output_handler *handler = *(php_output_handler **) h;
php_output_context *context = (php_output_context *) c; php_output_context *context = (php_output_context *) c;
@ -1097,9 +1117,7 @@ static int php_output_stack_apply_op(void *h, void *c)
if ((was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) { if ((was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
status = PHP_OUTPUT_HANDLER_FAILURE; status = PHP_OUTPUT_HANDLER_FAILURE;
} else { } else {
op = context->op;
status = php_output_handler_op(handler, context); status = php_output_handler_op(handler, context);
context->op = op;
} }
/* /*

View file

@ -81,7 +81,7 @@ typedef enum _php_output_handler_hook_t {
#define PHP_OUTPUT_HANDLER_INITBUF_SIZE(s) \ #define PHP_OUTPUT_HANDLER_INITBUF_SIZE(s) \
( (s) ? \ ( (s) ? \
(s) + PHP_OUTPUT_HANDLER_ALIGNTO_SIZE - ((s) % (PHP_OUTPUT_HANDLER_ALIGNTO_SIZE >> 2)) : \ (s) + PHP_OUTPUT_HANDLER_ALIGNTO_SIZE - ((s) % (PHP_OUTPUT_HANDLER_ALIGNTO_SIZE)) : \
PHP_OUTPUT_HANDLER_DEFAULT_SIZE \ PHP_OUTPUT_HANDLER_DEFAULT_SIZE \
) )
#define PHP_OUTPUT_HANDLER_ALIGNTO_SIZE 0x1000 #define PHP_OUTPUT_HANDLER_ALIGNTO_SIZE 0x1000