diff --git a/NEWS b/NEWS index 52b1b8250abc8..78c4b7cfb173e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2013, PHP 5.3.21 +- Zend Engine: + . Fixed bug #63762 (Sigsegv when Exception::$trace is changed by user). + (Johannes) + ?? ??? 2012, PHP 5.3.20 #### ADD NEWS TO 5.3.21 ONLY #### diff --git a/Zend/tests/bug63762.phpt b/Zend/tests/bug63762.phpt new file mode 100644 index 0000000000000..8de177dcf83fb --- /dev/null +++ b/Zend/tests/bug63762.phpt @@ -0,0 +1,53 @@ +--TEST-- +Bug #63762 - Sigsegv when Exception::$trace is changed by user +--FILE-- +setAccessible(TRUE); + +echo "Array of NULL:\n"; +$ref->setValue($e, array(NULL)); + +var_dump($e->getTraceAsString()); + +echo "\nArray of empty array:\n"; +$ref->setValue($e, array(array())); +var_dump($e->getTraceAsString()); + +echo "\nArray of array of NULL values:\n"; +$ref->setValue($e, array(array( + 'file' => NULL, + 'line' => NULL, + 'class' => NULL, + 'type' => NULL, + 'function' => NULL, + 'args' => NULL +))); +var_dump($e->getTraceAsString()); +?> +--EXPECTF-- +Array of NULL: + +Warning: Expected array for frame 0 in %s on line %d +string(9) "#0 {main}" + +Array of empty array: +string(36) "#0 [internal function]: () +#1 {main}" + +Array of array of NULL values: + +Warning: Function name is no string in %s on line %d + +Warning: Value for class is no string in %s on line %d + +Warning: Value for type is no string in %s on line %d + +Warning: Value for function is no string in %s on line %d + +Warning: args element is no array in %s on line %d +string(60) "#0 [unknown function][unknown][unknown][unknown]() +#1 {main}" + diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index a83053e120662..e947a97ac380b 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -337,9 +337,14 @@ ZEND_METHOD(error_exception, getSeverity) #define TRACE_APPEND_STR(val) \ TRACE_APPEND_STRL(val, sizeof(val)-1) -#define TRACE_APPEND_KEY(key) \ - if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \ - TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \ +#define TRACE_APPEND_KEY(key) \ + if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \ + if (Z_TYPE_PP(tmp) != IS_STRING) { \ + zend_error(E_WARNING, "Value for %s is no string", key); \ + TRACE_APPEND_STR("[unknown]"); \ + } else { \ + TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \ + } \ } /* }}} */ @@ -448,6 +453,11 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg HashTable *ht = Z_ARRVAL_PP(frame); zval **file, **tmp; + if (Z_TYPE_PP(frame) != IS_ARRAY) { + zend_error(E_WARNING, "Expected array for frame %lu", hash_key->h); + return ZEND_HASH_APPLY_KEEP; + } + str = va_arg(args, char**); len = va_arg(args, int*); num = va_arg(args, int*); @@ -457,15 +467,25 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); efree(s_tmp); if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) { - if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) { - line = Z_LVAL_PP(tmp); - } else { - line = 0; + if (Z_TYPE_PP(file) != IS_STRING) { + zend_error(E_WARNING, "Function name is no string"); + TRACE_APPEND_STR("[unknown function]"); + } else{ + if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) { + if (Z_TYPE_PP(tmp) == IS_LONG) { + line = Z_LVAL_PP(tmp); + } else { + zend_error(E_WARNING, "Line is no long"); + line = 0; + } + } else { + line = 0; + } + s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1); + sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line); + TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); + efree(s_tmp); } - s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1); - sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line); - TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); - efree(s_tmp); } else { TRACE_APPEND_STR("[internal function]: "); } @@ -474,10 +494,14 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg TRACE_APPEND_KEY("function"); TRACE_APPEND_CHR('('); if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) { - int last_len = *len; - zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)_build_trace_args, 2, str, len); - if (last_len != *len) { - *len -= 2; /* remove last ', ' */ + if (Z_TYPE_PP(tmp) == IS_ARRAY) { + int last_len = *len; + zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)_build_trace_args, 2, str, len); + if (last_len != *len) { + *len -= 2; /* remove last ', ' */ + } + } else { + zend_error(E_WARNING, "args element is no array"); } } TRACE_APPEND_STR(")\n");