Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Zend/tests/exception_hooks_leak.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Overridden Exception get hooks don't leak
--CREDITS--
Saad Fellahi (TarPeg007)
--FILE--
<?php

class E extends Exception {
public string $file { get => $this->file . '!'; }
public $message { get => $this->message . '!'; }
}

$e = new E('Foo');

var_dump($e->getFile());
var_dump($e->getMessage());
echo $e, "\n";

?>
--EXPECTF--
string(%d) "%sexception_hooks_leak.php!"
string(4) "Foo!"
E: Foo! in %s:%d
Stack trace:
#0 {main}
27 changes: 18 additions & 9 deletions Zend/zend_exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,15 @@ ZEND_METHOD(ErrorException, __construct)
#define GET_PROPERTY_SILENT(object, id) \
zend_read_property_ex(i_get_exception_base(Z_OBJ_P(object)), Z_OBJ_P(object), ZSTR_KNOWN(id), 1, &rv)

static zend_always_inline zend_string *zval_get_owned_string(zval *op, zval *rv) {
zend_string *result = zval_get_string(op);
if (op == rv) {
zval_ptr_dtor(rv);
}
return result;
}
#define ZVAL_GET_OWNED_STRING(op) (zval_get_owned_string(op, &rv))

/* {{{ Get the file in which the exception occurred */
ZEND_METHOD(Exception, getFile)
{
Expand All @@ -447,7 +456,7 @@ ZEND_METHOD(Exception, getFile)
ZEND_PARSE_PARAMETERS_NONE();

prop = GET_PROPERTY(ZEND_THIS, ZEND_STR_FILE);
RETURN_STR(zval_get_string(prop));
RETURN_STR(ZVAL_GET_OWNED_STRING(prop));
}
/* }}} */

Expand All @@ -471,7 +480,7 @@ ZEND_METHOD(Exception, getMessage)
ZEND_PARSE_PARAMETERS_NONE();

prop = GET_PROPERTY(ZEND_THIS, ZEND_STR_MESSAGE);
RETURN_STR(zval_get_string(prop));
RETURN_STR(ZVAL_GET_OWNED_STRING(prop));
}
/* }}} */

Expand Down Expand Up @@ -698,8 +707,8 @@ ZEND_METHOD(Exception, __toString)

while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), zend_ce_throwable)) {
zend_string *prev_str = str;
zend_string *message = zval_get_string(GET_PROPERTY(exception, ZEND_STR_MESSAGE));
zend_string *file = zval_get_string(GET_PROPERTY(exception, ZEND_STR_FILE));
zend_string *message = ZVAL_GET_OWNED_STRING(GET_PROPERTY(exception, ZEND_STR_MESSAGE));
zend_string *file = ZVAL_GET_OWNED_STRING(GET_PROPERTY(exception, ZEND_STR_FILE));
zend_long line = zval_get_long(GET_PROPERTY(exception, ZEND_STR_LINE));

fci.size = sizeof(fci);
Expand Down Expand Up @@ -938,8 +947,8 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severit
ce_exception = ex->ce;
EG(exception) = NULL;
if (ce_exception == zend_ce_parse_error || ce_exception == zend_ce_compile_error) {
zend_string *message = zval_get_string(GET_PROPERTY(&exception, ZEND_STR_MESSAGE));
zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
zend_string *message = ZVAL_GET_OWNED_STRING(GET_PROPERTY(&exception, ZEND_STR_MESSAGE));
zend_string *file = ZVAL_GET_OWNED_STRING(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
int type = (ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL;

Expand Down Expand Up @@ -969,7 +978,7 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severit
ZVAL_OBJ(&zv, EG(exception));
/* do the best we can to inform about the inner exception */
if (instanceof_function(ce_exception, zend_ce_exception) || instanceof_function(ce_exception, zend_ce_error)) {
file = zval_get_string(GET_PROPERTY_SILENT(&zv, ZEND_STR_FILE));
file = ZVAL_GET_OWNED_STRING(GET_PROPERTY_SILENT(&zv, ZEND_STR_FILE));
line = zval_get_long(GET_PROPERTY_SILENT(&zv, ZEND_STR_LINE));
}

Expand All @@ -982,8 +991,8 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severit
}
}

str = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_STRING));
file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
str = ZVAL_GET_OWNED_STRING(GET_PROPERTY_SILENT(&exception, ZEND_STR_STRING));
file = ZVAL_GET_OWNED_STRING(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));

zend_error_va(severity | E_DONT_BAIL,
Expand Down
Loading