Skip to content

Property hooks #122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b7c5813
Update libmagic to 5.45 (#13369)
nielsdos Feb 13, 2024
c2b671c
Fix GH-13344: finfo::buffer(): Failed identify data 0:(null)
nielsdos Feb 11, 2024
e71b597
Merge branch 'PHP-8.2' into PHP-8.3
nielsdos Feb 13, 2024
be34b96
Merge branch 'PHP-8.3'
nielsdos Feb 13, 2024
5941cda
Fix ZTS crashes with persistent resources in modules (#13381)
nielsdos Feb 13, 2024
e957e25
Move constants from dir.c to stub file (#13312)
haszi Feb 13, 2024
844c1ac
Add missing --EXTENSIONS-- section from frameless function inference …
kocsismate Feb 13, 2024
aa1eaac
zend_ssa minor struct changes. (#13387)
devnexen Feb 14, 2024
b222c02
Fix linking ext/curl against OpenSSL (#13262)
petk Feb 14, 2024
1e770d1
Use Autoconf AC_CHECK_TYPE for checking siginfo_t (#13389)
petk Feb 14, 2024
ce96aa9
Update IR
dstogov Feb 14, 2024
9588796
Use AC_CHECK_TYPES for checking struct flock (#13397)
petk Feb 15, 2024
87abd50
Fix 32-bit fileinfo (#13404)
nielsdos Feb 15, 2024
f6016c7
ext/ldap: Add LDAP_OPT_X_TLS_PROTOCOL_MAX and LDAP_OPT_X_TLS_PROTOCOL…
StephenWall Feb 15, 2024
1f7cba2
Update IR
dstogov Feb 15, 2024
f84d046
add support for Zend Max Exeuction Timers on FreeBSD (#13393)
dunglas Feb 16, 2024
2065829
[ci skip] NEWS
arnaud-lb Feb 16, 2024
51591ab
[ci skip] Adding myself as reviewer
arnaud-lb Feb 16, 2024
9a034c9
[ci skip] Adding myself as reviewer
arnaud-lb Feb 16, 2024
babe818
[ci skip] Merge branch 'PHP-8.3'
arnaud-lb Feb 16, 2024
2592398
Refactor PHP_SOCKADDR_CHECKS (#13406)
petk Feb 16, 2024
b5c3cbf
Check sockaddr_storage.ss_family with AC_CHECK_MEMBERS (#13407)
petk Feb 16, 2024
eaaffae
zend_call_stack sort of GH-13358 follow-up. (#13368)
devnexen Feb 16, 2024
e7b1f2a
Change long2ip return type (#13395)
jorgsowa Feb 16, 2024
492b9e0
Add entry on return type of long2ip to NEWS (#13408)
jorgsowa Feb 16, 2024
0941507
ext/ldap: few new unit tests (tls13 protocol). (#13409)
devnexen Feb 16, 2024
68ae82c
Accessors implementation
iluuu1994 Apr 20, 2023
fd48ffc
Various adjustments
iluuu1994 Feb 1, 2024
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
4 changes: 3 additions & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@
/Zend/zend.* @dstogov
/Zend/zend_alloc.* @dstogov
/Zend/zend_API.* @dstogov
/Zend/zend_call_stack.* @arnaud-lb
/Zend/zend_closures.* @dstogov
/Zend/zend_execute.* @dstogov
/Zend/zend_execute_API.c @dstogov
/Zend/zend_gc.* @dstogov
/Zend/zend_gc.* @dstogov @arnaud-lb
/Zend/zend_hash.* @dstogov
/Zend/zend_inheritance.* @dstogov
/Zend/zend_max_execution_timer.* @arnaud-lb
/Zend/zend_object_handlers.* @dstogov
/Zend/zend_objects.* @dstogov
/Zend/zend_objects_API.* @dstogov
Expand Down
9 changes: 9 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ PHP NEWS
array to hashed). (ilutov)
. Fixed zend fiber build for solaris default mode (32 bits). (David Carlier)
. Fixed zend call stack size for macOs/arm64. (David Carlier)
. Added support for Zend Max Execution Timers on FreeBSD (Kévin Dunglas)

- Curl:
. Deprecated the CURLOPT_BINARYTRANSFER constant. (divinity76)
Expand All @@ -32,6 +33,9 @@ PHP NEWS
. Handle OOM more consistently. (nielsdos)
. Implemented "Improve callbacks in ext/dom and ext/xsl" RFC. (nielsdos)

- Fileinfo:
. Update to libmagic 5.45. (nielsdos)

- FPM:
. Implement GH-12385 (flush headers without body when calling flush()).
(nielsdos)
Expand All @@ -55,6 +59,10 @@ PHP NEWS
aliases for ::ROUND_DOWN and ::ROUND_UP. (Jorg Sowa)
. Added NumberFormatter::ROUND_HALFODD. (Ayesh Karunaratne)

- LDAP:
. Added LDAP_OPT_X_TLS_PROTOCOL_MAX/LDAP_OPT_X_TLS_PROTOCOL_TLS1_3
constants. (StephenWall)

- MBString:
. Added mb_trim, mb_ltrim and mb_rtrim. (Yuya Hamada)

Expand Down Expand Up @@ -167,6 +175,7 @@ PHP NEWS
. Add support for 4 new rounding modes to the round() function. (Jorg Sowa)
. debug_zval_dump() now indicates whether an array is packed. (Max Semenik)
. Fix GH-12143 (Optimize round). (SakiTakamachi)
. Changed return type of long2ip to string from string|false. (Jorg Sowa)

- XML:
. Added XML_OPTION_PARSE_HUGE parser option. (nielsdos)
Expand Down
21 changes: 21 additions & 0 deletions TSRM/TSRM.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,27 @@ void ts_free_id(ts_rsrc_id id)
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id));
}/*}}}*/

TSRM_API void ts_apply_for_id(ts_rsrc_id id, void (*cb)(void *))
{
int rsrc_id = TSRM_UNSHUFFLE_RSRC_ID(id);

tsrm_mutex_lock(tsmm_mutex);

if (tsrm_tls_table && resource_types_table) {
for (int i = 0; i < tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i];

while (p) {
if (p->count > rsrc_id && p->storage[rsrc_id]) {
cb(p->storage[rsrc_id]);
}
p = p->next;
}
}
}

tsrm_mutex_unlock(tsmm_mutex);
}

/*
* Utility Functions
Expand Down
3 changes: 3 additions & 0 deletions TSRM/TSRM.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ TSRM_API void ts_free_thread(void);
/* deallocates all occurrences of a given id */
TSRM_API void ts_free_id(ts_rsrc_id id);

/* Runs a callback on all resources of the given id.
* The caller is responsible for ensuring the underlying resources don't data-race. */
TSRM_API void ts_apply_for_id(ts_rsrc_id id, void (*cb)(void *));

/* Debug support */
#define TSRM_ERROR_LEVEL_ERROR 1
Expand Down
5 changes: 5 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ PHP 8.4 UPGRADE NOTES
decimal number and round it to 0.29. However, "pre-rounding" incorrectly rounds
certain numbers, so this fix removes "pre-rounding" and changes the way numbers
are compared, so that the values ​​are correctly rounded as decimal numbers.
. long2ip() now returns string instead of string|false.

========================================
6. New Functions
Expand Down Expand Up @@ -446,6 +447,10 @@ PHP 8.4 UPGRADE NOTES
. The IntlDateFormatter class exposes now the new PATTERN constant
reflecting udat api's UDAT_PATTERN.

- LDAP:
. LDAP_OPT_X_TLS_PROTOCOL_MAX.
. LDAP_OPT_X_TLS_PROTOCOL_TLS1_3.

- OpenSSL:
. X509_PURPOSE_OCSP_HELPER.
. X509_PURPOSE_TIMESTAMP_SIGN.
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ PHP 8.4 INTERNALS UPGRADE NOTES
- Symbol HAVE_BSD_ICONV has been removed.
- M4 macro PHP_DEFINE (atomic includes) removed (use AC_DEFINE and config.h).
- M4 macro PHP_WITH_SHARED has been removed (use PHP_ARG_WITH).
- M4 macro PHP_STRUCT_FLOCK has been removed (use AC_CHECK_TYPES).
- M4 macro PHP_SOCKADDR_CHECKS has been removed (use AC_CHECK_TYPES and
AC_CHECK_MEMBERS).

c. Windows build system changes
- The configure options --with-oci8-11g, --with-oci8-12c, --with-oci8-19 have
Expand Down
3 changes: 3 additions & 0 deletions Zend/Optimizer/compact_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
LITERAL_INFO(opline->op2.constant, 2);
}
break;
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
LITERAL_INFO(opline->op1.constant, 1);
break;
case ZEND_CATCH:
LITERAL_INFO(opline->op1.constant, 2);
break;
Expand Down
7 changes: 6 additions & 1 deletion Zend/Optimizer/optimize_func_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static void zend_delete_call_instructions(zend_op_array *op_array, zend_op *opli
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_FCALL:
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
if (call == 0) {
MAKE_NOP(opline);
return;
Expand Down Expand Up @@ -169,12 +170,15 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_FCALL:
case ZEND_NEW:
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
/* The argument passing optimizations are valid for prototypes as well,
* as inheritance cannot change between ref <-> non-ref arguments. */
call_stack[call].func = zend_optimizer_get_called_func(
ctx->script, op_array, opline, &call_stack[call].is_prototype);
call_stack[call].try_inline =
!call_stack[call].is_prototype && opline->opcode != ZEND_NEW;
!call_stack[call].is_prototype
&& opline->opcode != ZEND_NEW
&& opline->opcode != ZEND_INIT_PARENT_PROPERTY_HOOK_CALL;
ZEND_FALLTHROUGH;
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_USER_CALL:
Expand Down Expand Up @@ -212,6 +216,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
}
} else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL
|| fcall->opcode == ZEND_INIT_METHOD_CALL
|| fcall->opcode == ZEND_INIT_PARENT_PROPERTY_HOOK_CALL
|| fcall->opcode == ZEND_NEW) {
/* We don't have specialized opcodes for this, do nothing */
} else {
Expand Down
1 change: 1 addition & 0 deletions Zend/Optimizer/zend_call_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32
case ZEND_INIT_FCALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
call_stack[call] = call_info;
func = zend_optimizer_get_called_func(
script, op_array, opline, &is_prototype);
Expand Down
2 changes: 1 addition & 1 deletion Zend/Optimizer/zend_func_infos.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ static const func_info_t func_infos[] = {
FN("array_rand", MAY_BE_LONG|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING),
F1("base64_encode", MAY_BE_STRING),
F1("base64_decode", MAY_BE_STRING|MAY_BE_FALSE),
F1("long2ip", MAY_BE_STRING|MAY_BE_FALSE),
F1("long2ip", MAY_BE_STRING),
F1("getenv", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE),
F1("getopt", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_FALSE|MAY_BE_FALSE),
#if defined(HAVE_NANOSLEEP)
Expand Down
35 changes: 35 additions & 0 deletions Zend/Optimizer/zend_optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,28 @@ zend_function *zend_optimizer_get_called_func(
}
}
break;
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL: {
zend_class_entry *scope = op_array->scope;
ZEND_ASSERT(scope != NULL);
if (scope && (scope->ce_flags & ZEND_ACC_LINKED) && scope->parent) {
zend_class_entry *parent_scope = scope->parent;
zend_string *prop_name = Z_STR_P(CRT_CONSTANT(opline->op1));
zend_property_hook_kind hook_kind = opline->op2.num;
zend_property_info *prop_info = zend_get_property_info(parent_scope, prop_name, /* silent */ true);

if (prop_info
&& prop_info != ZEND_WRONG_PROPERTY_INFO
&& !(prop_info->flags & ZEND_ACC_PRIVATE)
&& prop_info->hooks) {
zend_function *fbc = prop_info->hooks[hook_kind];
if (fbc) {
*is_prototype = false;
return fbc;
}
}
}
break;
}
case ZEND_NEW:
{
zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
Expand Down Expand Up @@ -1473,6 +1495,19 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void
zend_foreach_op_array_helper(op_array, func, context);
}
} ZEND_HASH_FOREACH_END();

zend_property_info *property;
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property) {
zend_function **hooks = property->hooks;
if (property->ce == ce && property->hooks) {
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
zend_function *hook = hooks[i];
if (hook && hook->common.scope == ce) {
zend_foreach_op_array_helper(&hooks[i]->op_array, func, context);
}
}
}
} ZEND_HASH_FOREACH_END();
} ZEND_HASH_FOREACH_END();
}

Expand Down
6 changes: 3 additions & 3 deletions Zend/Optimizer/zend_ssa.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct _zend_ssa_phi {
int var; /* Original CV, VAR or TMP variable index */
int ssa_var; /* SSA variable index */
int block; /* current BB index */
bool has_range_constraint : 1;
bool has_range_constraint;
zend_ssa_phi **use_chains;
zend_ssa_phi *sym_use_chain;
int *sources; /* Array of SSA IDs that produce this var.
Expand Down Expand Up @@ -112,8 +112,8 @@ typedef struct _zend_ssa_var {
zend_ssa_phi *definition_phi; /* phi that defines this value */
zend_ssa_phi *phi_use_chain; /* uses of this value in Phi, linked through use_chain */
zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constraints */
unsigned int no_val : 1; /* value doesn't matter (used as op1 in ZEND_ASSIGN) */
unsigned int scc_entry : 1;
bool no_val : 1; /* value doesn't matter (used as op1 in ZEND_ASSIGN) */
bool scc_entry : 1;
unsigned int alias : 2; /* value may be changed indirectly */
unsigned int escape_state : 2;
} zend_ssa_var;
Expand Down
2 changes: 1 addition & 1 deletion Zend/Zend.m4
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ AC_ARG_ENABLE([zend-max-execution-timers],
[ZEND_MAX_EXECUTION_TIMERS=$enableval],
[ZEND_MAX_EXECUTION_TIMERS=$ZEND_ZTS])

AS_CASE(["$host_alias"], [*linux*], [], [ZEND_MAX_EXECUTION_TIMERS='no'])
AS_CASE(["$host_alias"], [*linux*|*freebsd*], [], [ZEND_MAX_EXECUTION_TIMERS='no'])

PHP_CHECK_FUNC(timer_create, rt)
if test "$ac_cv_func_timer_create" != "yes"; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ const FOO_COMPILE_ERROR = "BAR"{0};
var_dump(FOO_COMPILE_ERROR);
?>
--EXPECTF--
Fatal error: Array and string offset access syntax with curly braces is no longer supported in %s on line 2
Parse error: syntax error, unexpected token "{", expecting "," or ";" in %s on line %d
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ $foo = 'BAR';
var_dump($foo{0});
?>
--EXPECTF--
Fatal error: Array and string offset access syntax with curly braces is no longer supported in %s on line 3
Parse error: syntax error, unexpected token "{", expecting ")" in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/alternative_offset_syntax_in_encaps_string.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Alternative offset syntax should emit only E_COMPILE_ERROR in string interpolati
--FILE--
<?php "{$g{'h'}}"; ?>
--EXPECTF--
Fatal error: Array and string offset access syntax with curly braces is no longer supported in %s on line 1
Parse error: syntax error, unexpected token "{", expecting "->" or "?->" or "[" in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/errmsg_037.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ class test {
echo "Done\n";
?>
--EXPECTF--
Fatal error: Cannot use the abstract modifier on a property in %s on line %d
Fatal error: Only hooked properties may be declared abstract in %s on line %d
13 changes: 0 additions & 13 deletions Zend/tests/errmsg_038.phpt

This file was deleted.

22 changes: 22 additions & 0 deletions Zend/tests/property_hooks/abstract_hook.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Abstract hooks compile successfully
--FILE--
<?php

abstract class A {
public $prop {
abstract get;
set {}
}
}

class B extends A {
public $prop {
get {}
}
}

?>
===DONE===
--EXPECT--
===DONE===
15 changes: 15 additions & 0 deletions Zend/tests/property_hooks/abstract_hook_in_non_abstract_class.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
Abstract hooks in non-abstract class gives an error
--FILE--
<?php

class Test {
public $prop {
abstract get;
set {}
}
}

?>
--EXPECTF--
Fatal error: Class Test contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Test::$prop::get) in %s on line %d
17 changes: 17 additions & 0 deletions Zend/tests/property_hooks/abstract_hook_not_implemented.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Abstract hooks that are not implemented throw an error
--FILE--
<?php

abstract class A {
public $prop {
abstract get;
set {}
}
}

class B extends A {}

?>
--EXPECTF--
Fatal error: Class B contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (A::$prop::get) in %s on line %d
12 changes: 12 additions & 0 deletions Zend/tests/property_hooks/abstract_prop_abstract_hook.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
Abstract property with abstract hook is redundant so invalid
--FILE--
<?php

class C {
abstract public $prop { abstract get; }
}

?>
--EXPECTF--
Fatal error: Property hook on abstract property cannot be explicitly abstract in %s on line %d
17 changes: 17 additions & 0 deletions Zend/tests/property_hooks/abstract_prop_hooks.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Explicit hooked property satisfies abstract property
--FILE--
<?php

abstract class A {
abstract public $prop { get; set; }
}

class B extends A {
public $prop { get {} set {} }
}

?>
===DONE===
--EXPECT--
===DONE===
14 changes: 14 additions & 0 deletions Zend/tests/property_hooks/abstract_prop_not_implemented.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
Abstract property not implemented throws an error
--FILE--
<?php

class A {
abstract public $prop { get; set; }
}

class B extends A {}

?>
--EXPECTF--
Fatal error: Class A contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (A::$prop::get, A::$prop::set) in %s on line %d
Loading