Skip to content

Commit d998054

Browse files
committed
Merge branch 'master' of github.com:php/php-src
2 parents a50499b + b56492b commit d998054

File tree

10 files changed

+114
-39
lines changed

10 files changed

+114
-39
lines changed

Zend/tests/gh9136.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
GH-9136: Assertion when fetching property of magic constant in constant expression
3+
--FILE--
4+
<?php
5+
6+
const C = __file__->foo;
7+
8+
?>
9+
--EXPECTF--
10+
Warning: Attempt to read property "foo" on string in %s on line %d

Zend/tests/gh9138.phpt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
GH-9138: NULL pointer dereference when fetching property of "bad" list in constant expression
3+
--FILE--
4+
<?php
5+
6+
#[Attribute([,]->e)]
7+
class Foo {}
8+
9+
?>
10+
--EXPECTF--
11+
Fatal error: Cannot use empty array elements in arrays in %s on line %d

Zend/zend_closures.c

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ ZEND_METHOD(Closure, call)
121121
zend_closure *closure;
122122
zend_fcall_info fci;
123123
zend_fcall_info_cache fci_cache;
124-
zend_function my_function;
125124
zend_object *newobj;
126125
zend_class_entry *newclass;
127126

@@ -142,55 +141,71 @@ ZEND_METHOD(Closure, call)
142141
return;
143142
}
144143

144+
fci_cache.called_scope = newclass;
145+
fci_cache.object = fci.object = newobj;
146+
147+
fci.size = sizeof(fci);
148+
ZVAL_OBJ(&fci.function_name, &closure->std);
149+
ZVAL_UNDEF(&closure_result);
150+
fci.retval = &closure_result;
151+
145152
if (closure->func.common.fn_flags & ZEND_ACC_GENERATOR) {
146153
zval new_closure;
147154
zend_create_closure(&new_closure, &closure->func, newclass, closure->called_scope, newthis);
148155
closure = (zend_closure *) Z_OBJ(new_closure);
149156
fci_cache.function_handler = &closure->func;
157+
158+
zend_call_function(&fci, &fci_cache);
159+
160+
/* copied upon generator creation */
161+
GC_DELREF(&closure->std);
150162
} else {
151-
memcpy(&my_function, &closure->func, closure->func.type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
152-
my_function.common.fn_flags &= ~ZEND_ACC_CLOSURE;
163+
zend_function *my_function;
164+
if (ZEND_USER_CODE(closure->func.type)) {
165+
my_function = emalloc(sizeof(zend_op_array));
166+
memcpy(my_function, &closure->func, sizeof(zend_op_array));
167+
} else {
168+
my_function = emalloc(sizeof(zend_internal_function));
169+
memcpy(my_function, &closure->func, sizeof(zend_internal_function));
170+
}
171+
my_function->common.fn_flags &= ~ZEND_ACC_CLOSURE;
153172
/* use scope of passed object */
154-
my_function.common.scope = newclass;
173+
my_function->common.scope = newclass;
155174
if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
156-
my_function.internal_function.handler = closure->orig_internal_handler;
175+
my_function->internal_function.handler = closure->orig_internal_handler;
157176
}
158-
fci_cache.function_handler = &my_function;
177+
fci_cache.function_handler = my_function;
159178

160179
/* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */
161-
if (ZEND_USER_CODE(my_function.type)
180+
if (ZEND_USER_CODE(my_function->type)
162181
&& (closure->func.common.scope != newclass
163182
|| (closure->func.common.fn_flags & ZEND_ACC_HEAP_RT_CACHE))) {
164183
void *ptr;
165184

166-
my_function.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
167-
ptr = emalloc(my_function.op_array.cache_size);
168-
ZEND_MAP_PTR_INIT(my_function.op_array.run_time_cache, ptr);
169-
memset(ptr, 0, my_function.op_array.cache_size);
185+
my_function->op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
186+
ptr = emalloc(my_function->op_array.cache_size);
187+
ZEND_MAP_PTR_INIT(my_function->op_array.run_time_cache, ptr);
188+
memset(ptr, 0, my_function->op_array.cache_size);
170189
}
171-
}
172190

173-
fci_cache.called_scope = newclass;
174-
fci_cache.object = fci.object = newobj;
191+
zend_call_function(&fci, &fci_cache);
175192

176-
fci.size = sizeof(fci);
177-
ZVAL_OBJ(&fci.function_name, &closure->std);
178-
fci.retval = &closure_result;
193+
if (ZEND_USER_CODE(my_function->type)) {
194+
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) {
195+
efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache));
196+
}
197+
efree_size(my_function, sizeof(zend_op_array));
198+
} else {
199+
efree_size(my_function, sizeof(zend_internal_function));
200+
}
201+
}
179202

180-
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
203+
if (Z_TYPE(closure_result) != IS_UNDEF) {
181204
if (Z_ISREF(closure_result)) {
182205
zend_unwrap_reference(&closure_result);
183206
}
184207
ZVAL_COPY_VALUE(return_value, &closure_result);
185208
}
186-
187-
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
188-
/* copied upon generator creation */
189-
GC_DELREF(&closure->std);
190-
} else if (ZEND_USER_CODE(my_function.type)
191-
&& (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE)) {
192-
efree(ZEND_MAP_PTR(my_function.op_array.run_time_cache));
193-
}
194209
}
195210
/* }}} */
196211

Zend/zend_compile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10616,6 +10616,10 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
1061610616
case ZEND_AST_CONST_ENUM_INIT:
1061710617
zend_eval_const_expr(&ast->child[2]);
1061810618
return;
10619+
case ZEND_AST_PROP:
10620+
zend_eval_const_expr(&ast->child[0]);
10621+
zend_eval_const_expr(&ast->child[1]);
10622+
return;
1061910623
default:
1062010624
return;
1062110625
}

build/gen_stub.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,12 @@ public function toOptimizerTypeMask(): string {
533533
}
534534

535535
public function toEscapedName(): string {
536-
return str_replace('\\', '\\\\', $this->name);
536+
// Escape backslashes, and also encode \u and \U to avoid compilation errors in generated macros
537+
return str_replace(
538+
['\\', '\\u', '\\U'],
539+
['\\\\', '\\\\165', '\\\\125'],
540+
$this->name
541+
);
537542
}
538543

539544
public function toVarEscapedName(): string {
@@ -2976,7 +2981,7 @@ private function collectInheritedMembers(
29762981
$parentInfo->collectInheritedMembers(
29772982
$parentsWithInheritedConstants,
29782983
$unusedParentsWithInheritedProperties,
2979-
$parentsWithInheritedMethods,
2984+
$unusedParentsWithInheritedMethods,
29802985
$classMap
29812986
);
29822987
}

ext/openssl/openssl.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7652,15 +7652,6 @@ PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_le
76527652
}
76537653
buffer = zend_string_alloc(buffer_length, 0);
76547654

7655-
#ifdef PHP_WIN32
7656-
/* random/urandom equivalent on Windows */
7657-
if (php_win32_get_random_bytes((unsigned char*)(buffer)->val, (size_t) buffer_length) == FAILURE){
7658-
zend_string_release_ex(buffer, 0);
7659-
zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
7660-
return NULL;
7661-
}
7662-
#else
7663-
76647655
PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(buffer_length, length);
76657656
PHP_OPENSSL_RAND_ADD_TIME();
76667657
if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) {
@@ -7670,7 +7661,7 @@ PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_le
76707661
} else {
76717662
php_openssl_store_errors();
76727663
}
7673-
#endif
7664+
76747665
return buffer;
76757666
}
76767667

ext/zend_test/test.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
4343
static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
4444
static zend_class_entry *zend_test_forbid_dynamic_call;
4545
static zend_class_entry *zend_test_ns_foo_class;
46+
static zend_class_entry *zend_test_ns_unlikely_compile_error_class;
4647
static zend_class_entry *zend_test_ns2_foo_class;
4748
static zend_class_entry *zend_test_ns2_ns_foo_class;
4849
static zend_class_entry *zend_test_unit_enum;
@@ -535,6 +536,13 @@ static ZEND_METHOD(ZendTestNS_Foo, method)
535536
RETURN_LONG(0);
536537
}
537538

539+
static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method)
540+
{
541+
ZEND_PARSE_PARAMETERS_NONE();
542+
543+
RETURN_NULL();
544+
}
545+
538546
static ZEND_METHOD(ZendTestNS2_Foo, method)
539547
{
540548
ZEND_PARSE_PARAMETERS_NONE();
@@ -698,6 +706,7 @@ PHP_MINIT_FUNCTION(zend_test)
698706
zend_test_forbid_dynamic_call = register_class_ZendTestForbidDynamicCall();
699707

700708
zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
709+
zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError();
701710
zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
702711
zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();
703712

ext/zend_test/test.stub.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ class Foo {
150150
public function method(): int {}
151151
}
152152

153+
class UnlikelyCompileError {
154+
/* This method signature would create a compile error due to the string
155+
* "ZendTestNS\UnlikelyCompileError" in the generated macro call */
156+
public function method(): ?UnlikelyCompileError {}
157+
}
158+
153159
}
154160

155161
namespace ZendTestNS2 {

ext/zend_test/test_arginfo.h

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/zend_test/tests/gen_stub_test_01.phpt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ $foo = new \ZendTestNS2\Foo();
99
var_dump($foo);
1010
$foo->foo = new \ZendTestNS2\ZendSubNS\Foo();
1111
var_dump($foo);
12+
$foo = new \ZendTestNS\UnlikelyCompileError();
13+
var_dump($foo);
1214
?>
1315
--EXPECTF--
1416
object(ZendTestNS2\Foo)#%d (%d) {
@@ -20,3 +22,5 @@ object(ZendTestNS2\Foo)#%d (%d) {
2022
object(ZendTestNS2\ZendSubNS\Foo)#%d (%d) {
2123
}
2224
}
25+
object(ZendTestNS\UnlikelyCompileError)#%d (%d) {
26+
}

0 commit comments

Comments
 (0)