summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rwxr-xr-xZend/tests/bug41633_3.phpt12
-rw-r--r--Zend/zend_execute_API.c10
3 files changed, 23 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 917d5ec6ac..910ff24796 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,8 @@ PHP NEWS
- Fixed bug #41655 (open_basedir bypass via glob()). (Ilia)
- Fixed bug #41640 (get_class_vars produces error on class constants).
(Johannes)
+- Fixed bug #41633 (Crash instantiating classes with self-referencing
+ constants). (Dmitry)
- Fixed bug #41630 (segfault when an invalid color index is present in
the image data). (Reported by Elliot <wccoder@gmail dot com>) (Pierre)
- Fixed bug #41608 (segfault on a weird code with objects and switch()).
diff --git a/Zend/tests/bug41633_3.phpt b/Zend/tests/bug41633_3.phpt
new file mode 100755
index 0000000000..7b9452db85
--- /dev/null
+++ b/Zend/tests/bug41633_3.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #41633.3 (Crash instantiating classes with self-referencing constants)
+--FILE--
+<?php
+class Foo {
+ const A = Foo::B;
+ const B = Foo::A;
+}
+echo Foo::A;
+?>
+--EXPECTF--
+Fatal error: Cannot declare self-referencing constant 'Foo::B' in %sbug41633_3.php on line %d
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index f3a123e390..b57834f395 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -448,6 +448,10 @@ ZEND_API int zend_is_true(zval *op)
#include "../TSRM/tsrm_strtok_r.h"
+#define IS_VISITED_CONSTANT IS_CONSTANT_INDEX
+#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
+#define MARK_CONSTANT_VISITED(p) Z_TYPE_P(p) |= IS_VISITED_CONSTANT
+
ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC)
{
zval *p = *pp;
@@ -455,13 +459,17 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
zval const_value;
char *colon;
- if (Z_TYPE_P(p) == IS_CONSTANT) {
+ if (IS_CONSTANT_VISITED(p)) {
+ zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
+ } else if (Z_TYPE_P(p) == IS_CONSTANT) {
int refcount;
zend_uchar is_ref;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
+ MARK_CONSTANT_VISITED(p);
+
refcount = p->refcount;
is_ref = p->is_ref;