You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added PHP compatible string offsets, so reading, writing, isset(), empty() and unset() on a string behave as they do in PHP, including negative offsets, out of range warnings, dynamically typed sources and for c in s#760
Added an unassigned-variable warning, on by default, for a local that is read but never assigned #2654
Changed
Widened the conditional-initialization warning to every local that can be read before it is assigned, instead of only one assigned exactly once in a deeper branch #2679
Fixed
Fixed Closure::bindTo(), Closure::bind() and Closure::call() dropping a closure's use (...) captures, which read back as null or crashed the process #2667
Fixed var_dump() and print_r() of a closure crashing the process on PHP 8.4 and later, and reporting the internal capture carrier as $this instead of the enclosing object on every version #2667
Fixed a compile error being replaced by a deprecation notice on PHP 8.4 and later, by marking six implicitly nullable parameters as nullable and letting a deprecation report as PHP reports it #2663
Fixed a by-reference call argument reading a copy of the container instead of its storage slot, which lost or aliased a write to a shared array, reported a missing element PHP creates, and freed the property's array when the callee replaced its argument #2691
Fixed a by-reference subscript argument borrowing the container value, which lost the write whenever the value was shared and leaked the offsetGet() result for an ArrayAccess container #2691
Fixed a read-only subscript read of an ArrayAccess object releasing the value offsetGet() owns, which leaked 96 bytes per call or corrupted the heap, and limited the read-only shortcut to a container proven to hold a native array #2682
Fixed explode() returning the limit = 2 result for a limit of 0, 1 or negative, and looping forever on an empty separator where PHP throws ValueError#2674
Fixed fetch and empty() on an ArrayAccess object releasing the string offset before offsetGet() received it, so the object was silently handed the key offsetget#2656
Fixed the array isset helpers never releasing the offsetExists() return value, and holding no reference to the container across the two userland calls, as PHP's own zend_std_read_dimension() does #2656
Fixed unset obj->property leaking the property name string on every call #2656
Fixed a leaked exception instance when a throw cannot construct its exception, a leaked callable when an internal call names an unknown function, and an uninitialized return slot in the zephir_return_call_*() helpers #2656
Fixed a declared but never assigned variable reaching userland as an uninitialized zval, printed by var_dump() as UNKNOWN:0, where PHP evaluates an unset variable as null#2654
Fixed a variable assigned only inside a conditional branch reaching userland as an uninitialized zval on a path that skips the assignment #2679
Fixed the zephir_array_*_long() helpers truncating a negative or large index to 32 bits on Windows, where unsigned long is narrower than zend_long, so s[-1] read index 4294967295 and a write tried to grow the string to 4 GB #2666
Fixed Zephir long/ulong mapping to a C long, 32-bit on Windows, so a 64-bit value truncated and Z_PARAM_LONG() stored 8 bytes into a 4-byte local #2666
Fixed the kernel signatures that carry a PHP integer (zephir_get_intval_ex(), the comparison, division and modulo helpers, zephir_substr(), zephir_fast_explode(), zephir_preg_match() and the multi-dimensional array key) using a C long#2666
Fixed a multi-dimensional array index reaching zephir_array_update_multi() as a C int where the callee reads a zend_long, so a[0][1] produced keys such as 140733193388033 on Windows #2666
Fixed a uint/ulong multi-dimensional array index being passed by address, so the pointer value became the array key #2666
Fixed six zephir_safe_mod_*() helpers being declared and emitted but never defined, so any % with a float operand died at load with undefined symbol#2666
Fixed % yielding a float instead of an int, which lost every result above 2^53 #2666
Fixed / 0 and % 0 raising an E_WARNING and returning 0 instead of throwing DivisionByZeroError as PHP 8 does #2666
Fixed PHP_INT_MIN % -1 crashing the process with SIGFPE #2666
Fixed a float divisor being silently truncated to an integer by / and %#2666
Fixed a -Wformat warning in zephir_fclose() by casting the resource handle to zend_long and formatting it with the portable ZEND_LONG_FMT macro instead of %d, preserving compatibility with PHP 8.0's int handle.
A variable whose only consumer is a closure's use (...) clause now counts as used: it is no longer reported as unused-variable, and it is declared in the generated C. A declared-but-unassigned capture was skipped by both, so the generated code referenced an undeclared identifier and the extension failed to build. Capturing a variable that was never declared now fails with Cannot capture variable 'x' because it wasn't declared instead of a PHP fatal error #2029
Fixed array defaults on a class (typed array property defaults, trait array property defaults and array class constants), which were one shared table that every instance mutated in place instead of being copy-on-write #2651
Fixed the unchecked length arithmetic in the zephir_concat_*() helpers, which now throw String size overflow like PHP instead of writing past the allocation #2657
Fixed let s .= n with an integer operand calling the declared but never defined zephir_concat_self_long(), so the extension built and then died at load with undefined symbol, and made the same append work on a var left-hand side #2660
Fixed closure use (...) captures being shared by every closure created from the same source line, and implemented use (&x) as a real reference #2652
Fixed the closure use (...) clause dropping const, which is now a read-only capture, and a by-reference capture of an explicitly typed local #2653
Fixed a closure declared inside another closure never having its source file generated, so the extension failed to link, and this inside it resolving against the outer closure instead of the enclosing class #2655
Fixed every closure invocation leaking one reference of the closure object and of each captured value #2652
This discussion was created from the release 1.4.0.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Added
isset(),empty()andunset()on a string behave as they do in PHP, including negative offsets, out of range warnings, dynamically typed sources andfor c in s#760unassigned-variablewarning, on by default, for a local that is read but never assigned #2654Changed
conditional-initializationwarning to every local that can be read before it is assigned, instead of only one assigned exactly once in a deeper branch #2679Fixed
Closure::bindTo(),Closure::bind()andClosure::call()dropping a closure'suse (...)captures, which read back asnullor crashed the process #2667var_dump()andprint_r()of a closure crashing the process on PHP 8.4 and later, and reporting the internal capture carrier as$thisinstead of the enclosing object on every version #2667offsetGet()result for anArrayAccesscontainer #2691ArrayAccessobject releasing the valueoffsetGet()owns, which leaked 96 bytes per call or corrupted the heap, and limited the read-only shortcut to a container proven to hold a native array #2682explode()returning thelimit = 2result for a limit of0,1or negative, and looping forever on an empty separator where PHP throwsValueError#2674fetchandempty()on anArrayAccessobject releasing the string offset beforeoffsetGet()received it, so the object was silently handed the keyoffsetget#2656issethelpers never releasing theoffsetExists()return value, and holding no reference to the container across the two userland calls, as PHP's ownzend_std_read_dimension()does #2656unset obj->propertyleaking the property name string on every call #2656throwcannot construct its exception, a leaked callable when an internal call names an unknown function, and an uninitialized return slot in thezephir_return_call_*()helpers #2656var_dump()asUNKNOWN:0, where PHP evaluates an unset variable asnull#2654zephir_array_*_long()helpers truncating a negative or large index to 32 bits on Windows, whereunsigned longis narrower thanzend_long, sos[-1]read index 4294967295 and a write tried to grow the string to 4 GB #2666long/ulongmapping to a Clong, 32-bit on Windows, so a 64-bit value truncated andZ_PARAM_LONG()stored 8 bytes into a 4-byte local #2666zephir_get_intval_ex(), the comparison, division and modulo helpers,zephir_substr(),zephir_fast_explode(),zephir_preg_match()and the multi-dimensional array key) using a Clong#2666zephir_array_update_multi()as a Cintwhere the callee reads azend_long, soa[0][1]produced keys such as 140733193388033 on Windows #2666uint/ulongmulti-dimensional array index being passed by address, so the pointer value became the array key #2666zephir_safe_mod_*()helpers being declared and emitted but never defined, so any%with a float operand died at load withundefined symbol#2666%yielding a float instead of anint, which lost every result above 2^53 #2666/ 0and% 0raising anE_WARNINGand returning 0 instead of throwingDivisionByZeroErroras PHP 8 does #2666PHP_INT_MIN % -1crashing the process with SIGFPE #2666/and%#2666-Wformatwarning inzephir_fclose()by casting the resource handle tozend_longand formatting it with the portableZEND_LONG_FMTmacro instead of%d, preserving compatibility with PHP 8.0'sinthandle.use (...)clause now counts as used: it is no longer reported asunused-variable, and it is declared in the generated C. A declared-but-unassigned capture was skipped by both, so the generated code referenced an undeclared identifier and the extension failed to build. Capturing a variable that was never declared now fails withCannot capture variable 'x' because it wasn't declaredinstead of a PHP fatal error #2029arrayproperty defaults, trait array property defaults and array class constants), which were one shared table that every instance mutated in place instead of being copy-on-write #2651zephir_concat_*()helpers, which now throwString size overflowlike PHP instead of writing past the allocation #2657let s .= nwith an integer operand calling the declared but never definedzephir_concat_self_long(), so the extension built and then died at load withundefined symbol, and made the same append work on avarleft-hand side #2660use (...)captures being shared by every closure created from the same source line, and implementeduse (&x)as a real reference #2652use (...)clause droppingconst, which is now a read-only capture, and a by-reference capture of an explicitly typed local #2653thisinside it resolving against the outer closure instead of the enclosing class #2655This discussion was created from the release 1.4.0.
All reactions