summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-05-28 12:23:37 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-05-28 13:55:38 +0200
commitaaae77f7f113d4a0a684e2615ef798703ccd089e (patch)
tree91e38963114c5394d2423ba5de23f5d9aa0e3084
parentc16dbed0c4ef031d7ee0cd86bd3fd88f594b5030 (diff)
downloadphp-git-aaae77f7f113d4a0a684e2615ef798703ccd089e.tar.gz
Make Exception::$trace typed array property
This is a private property, so we are allowed to add a type. The new declaration of the property is: private array $trace = []; This ensures that Exception::getTrace() does indeed return an array. Userland code that was modifying the property through refleciton may have to be adjusted to assign an array (instead of null, for example). Closes GH-5636.
-rw-r--r--Zend/zend_API.c14
-rw-r--r--Zend/zend_exceptions.c17
-rw-r--r--ext/standard/tests/serialize/bug69152.phpt6
-rw-r--r--ext/standard/tests/serialize/bug70963.phpt27
-rw-r--r--sapi/cli/tests/005.phpt4
5 files changed, 28 insertions, 40 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index ba5cb9c747..241cba8151 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3586,20 +3586,14 @@ ZEND_API int zend_declare_typed_property(zend_class_entry *ce, zend_string *name
Z_PROP_FLAG_P(property_default_ptr) = Z_ISUNDEF_P(property) ? IS_PROP_UNINIT : 0;
}
if (ce->type & ZEND_INTERNAL_CLASS) {
- switch(Z_TYPE_P(property)) {
- case IS_ARRAY:
- case IS_OBJECT:
- case IS_RESOURCE:
- zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
- break;
- default:
- break;
- }
-
/* Must be interned to avoid ZTS data races */
if (is_persistent_class(ce)) {
name = zend_new_interned_string(zend_string_copy(name));
}
+
+ if (Z_REFCOUNTED_P(property)) {
+ zend_error_noreturn(E_CORE_ERROR, "Internal zvals cannot be refcounted");
+ }
}
if (access_type & ZEND_ACC_PUBLIC) {
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 06c1c9897c..21775a26ca 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -606,10 +606,12 @@ ZEND_METHOD(Exception, getTraceAsString)
base_ce = i_get_exception_base(object);
trace = zend_read_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
- if (Z_TYPE_P(trace) != IS_ARRAY) {
- zend_type_error("Trace is not an array");
- return;
+ if (EG(exception)) {
+ RETURN_THROWS();
}
+
+ /* Type should be guaranteed by property type. */
+ ZEND_ASSERT(Z_TYPE_P(trace) == IS_ARRAY);
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
if (Z_TYPE_P(frame) != IS_ARRAY) {
zend_error(E_WARNING, "Expected array for frame " ZEND_ULONG_FMT, index);
@@ -736,12 +738,19 @@ ZEND_METHOD(Exception, __toString)
static void declare_exception_properties(zend_class_entry *ce)
{
+ zval val;
+
zend_declare_property_string(ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
zend_declare_property_string(ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
zend_declare_property_long(ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
zend_declare_property_null(ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
zend_declare_property_null(ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
- zend_declare_property_null(ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
+
+ ZVAL_EMPTY_ARRAY(&val);
+ zend_declare_typed_property(
+ ce, ZSTR_KNOWN(ZEND_STR_TRACE), &val, ZEND_ACC_PRIVATE, NULL,
+ (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY));
+
zend_declare_property_null(ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
}
diff --git a/ext/standard/tests/serialize/bug69152.phpt b/ext/standard/tests/serialize/bug69152.phpt
index b11591ffc2..f7f3b9ac8d 100644
--- a/ext/standard/tests/serialize/bug69152.phpt
+++ b/ext/standard/tests/serialize/bug69152.phpt
@@ -9,6 +9,8 @@ $x->test();
?>
--EXPECTF--
-Fatal error: Uncaught TypeError: Trace is not an array in %s:%d
-%a
+Fatal error: Uncaught TypeError: Cannot assign string to property Exception::$trace of type array in %s:%d
+Stack trace:
+#0 %s(%d): unserialize('O:9:"exception"...')
+#1 {main}
thrown in %s on line %d
diff --git a/ext/standard/tests/serialize/bug70963.phpt b/ext/standard/tests/serialize/bug70963.phpt
index c4e2267b04..63f5845ae0 100644
--- a/ext/standard/tests/serialize/bug70963.phpt
+++ b/ext/standard/tests/serialize/bug70963.phpt
@@ -6,25 +6,8 @@ var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."\0".'Exception'."\0".
var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."\0".'Exception'."\0".'trace";s:4:"test";}i:1;r:3;}'));
?>
--EXPECTF--
-array(2) {
- [0]=>
- object(Exception)#%d (6) {
- ["message":protected]=>
- string(0) ""
- ["string":"Exception":private]=>
- string(0) ""
- ["code":protected]=>
- int(0)
- ["file":protected]=>
- string(%d) "%s"
- ["line":protected]=>
- int(2)
- ["previous":"Exception":private]=>
- NULL
- }
- [1]=>
- string(4) "test"
-}
-
-Notice: unserialize(): Error at offset %d of %d bytes in %sbug70963.php on line 3
-bool(false)
+Fatal error: Uncaught TypeError: Cannot assign string to property Exception::$trace of type array in %s:%d
+Stack trace:
+#0 %s(%d): unserialize('a:2:{i:0;O:9:"e...')
+#1 {main}
+ thrown in %s on line %d
diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt
index 530b6cf29b..c037889c41 100644
--- a/sapi/cli/tests/005.phpt
+++ b/sapi/cli/tests/005.phpt
@@ -37,7 +37,7 @@ string(183) "Class [ <internal:Core> class stdClass ] {
}
"
-string(2159) "Class [ <internal:Core> class Exception implements Throwable, Stringable ] {
+string(2166) "Class [ <internal:Core> class Exception implements Throwable, Stringable ] {
- Constants [0] {
}
@@ -54,7 +54,7 @@ string(2159) "Class [ <internal:Core> class Exception implements Throwable, Stri
Property [ protected $code = 0 ]
Property [ protected $file = NULL ]
Property [ protected $line = NULL ]
- Property [ private $trace = NULL ]
+ Property [ private array $trace = Array ]
Property [ private $previous = NULL ]
}