Skip to content

Commit a11606b

Browse files
committed
Fix Bug #63762 Sigsegv when Exception::$trace is changed by user
1 parent 39a3007 commit a11606b

File tree

3 files changed

+96
-15
lines changed

3 files changed

+96
-15
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2013, PHP 5.3.21
44

5+
- Zend Engine:
6+
. Fixed bug #63762 (Sigsegv when Exception::$trace is changed by user).
7+
(Johannes)
8+
59
?? ??? 2012, PHP 5.3.20
610

711
#### ADD NEWS TO 5.3.21 ONLY ####

Zend/tests/bug63762.phpt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Bug #63762 - Sigsegv when Exception::$trace is changed by user
3+
--FILE--
4+
<?php
5+
$e = new Exception();
6+
7+
$ref = new ReflectionProperty($e, 'trace');
8+
$ref->setAccessible(TRUE);
9+
10+
echo "Array of NULL:\n";
11+
$ref->setValue($e, array(NULL));
12+
13+
var_dump($e->getTraceAsString());
14+
15+
echo "\nArray of empty array:\n";
16+
$ref->setValue($e, array(array()));
17+
var_dump($e->getTraceAsString());
18+
19+
echo "\nArray of array of NULL values:\n";
20+
$ref->setValue($e, array(array(
21+
'file' => NULL,
22+
'line' => NULL,
23+
'class' => NULL,
24+
'type' => NULL,
25+
'function' => NULL,
26+
'args' => NULL
27+
)));
28+
var_dump($e->getTraceAsString());
29+
?>
30+
--EXPECTF--
31+
Array of NULL:
32+
33+
Warning: Expected array for frame 0 in %s on line %d
34+
string(9) "#0 {main}"
35+
36+
Array of empty array:
37+
string(36) "#0 [internal function]: ()
38+
#1 {main}"
39+
40+
Array of array of NULL values:
41+
42+
Warning: Function name is no string in %s on line %d
43+
44+
Warning: Value for class is no string in %s on line %d
45+
46+
Warning: Value for type is no string in %s on line %d
47+
48+
Warning: Value for function is no string in %s on line %d
49+
50+
Warning: args element is no array in %s on line %d
51+
string(60) "#0 [unknown function][unknown][unknown][unknown]()
52+
#1 {main}"
53+

Zend/zend_exceptions.c

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,14 @@ ZEND_METHOD(error_exception, getSeverity)
337337
#define TRACE_APPEND_STR(val) \
338338
TRACE_APPEND_STRL(val, sizeof(val)-1)
339339

340-
#define TRACE_APPEND_KEY(key) \
341-
if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
342-
TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
340+
#define TRACE_APPEND_KEY(key) \
341+
if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
342+
if (Z_TYPE_PP(tmp) != IS_STRING) { \
343+
zend_error(E_WARNING, "Value for %s is no string", key); \
344+
TRACE_APPEND_STR("[unknown]"); \
345+
} else { \
346+
TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
347+
} \
343348
}
344349

345350
/* }}} */
@@ -448,6 +453,11 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
448453
HashTable *ht = Z_ARRVAL_PP(frame);
449454
zval **file, **tmp;
450455

456+
if (Z_TYPE_PP(frame) != IS_ARRAY) {
457+
zend_error(E_WARNING, "Expected array for frame %lu", hash_key->h);
458+
return ZEND_HASH_APPLY_KEEP;
459+
}
460+
451461
str = va_arg(args, char**);
452462
len = va_arg(args, int*);
453463
num = va_arg(args, int*);
@@ -457,15 +467,25 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
457467
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
458468
efree(s_tmp);
459469
if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
460-
if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
461-
line = Z_LVAL_PP(tmp);
462-
} else {
463-
line = 0;
470+
if (Z_TYPE_PP(file) != IS_STRING) {
471+
zend_error(E_WARNING, "Function name is no string");
472+
TRACE_APPEND_STR("[unknown function]");
473+
} else{
474+
if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
475+
if (Z_TYPE_PP(tmp) == IS_LONG) {
476+
line = Z_LVAL_PP(tmp);
477+
} else {
478+
zend_error(E_WARNING, "Line is no long");
479+
line = 0;
480+
}
481+
} else {
482+
line = 0;
483+
}
484+
s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
485+
sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
486+
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
487+
efree(s_tmp);
464488
}
465-
s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
466-
sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
467-
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
468-
efree(s_tmp);
469489
} else {
470490
TRACE_APPEND_STR("[internal function]: ");
471491
}
@@ -474,10 +494,14 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
474494
TRACE_APPEND_KEY("function");
475495
TRACE_APPEND_CHR('(');
476496
if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
477-
int last_len = *len;
478-
zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)_build_trace_args, 2, str, len);
479-
if (last_len != *len) {
480-
*len -= 2; /* remove last ', ' */
497+
if (Z_TYPE_PP(tmp) == IS_ARRAY) {
498+
int last_len = *len;
499+
zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)_build_trace_args, 2, str, len);
500+
if (last_len != *len) {
501+
*len -= 2; /* remove last ', ' */
502+
}
503+
} else {
504+
zend_error(E_WARNING, "args element is no array");
481505
}
482506
}
483507
TRACE_APPEND_STR(")\n");

0 commit comments

Comments
 (0)