Since GH-15021 preloaded constants are propagated to compiled scripts. This is
problematic for file cache, which assumes all referenced zvals are either
persistently allocated or local to the current script. However, preloaded
constants live in shm as immutable, but not persistent.
To solve this, we'd need to duplicate propagated constants in the optimizer when
file cache is used. This is error prone given it needs to happen in many places.
It's debatable whether constant propagation is even correct in this case, as
running the preloaded script on a restart isn't guaranteed to produce the same
result.
Hence, avoid the issue for now by just not relying on preloaded symbols when
file cache is used.
Fixes GH-21052
Closes GH-21281
Move the signal table update after the php_signal4 call, mirroring
what is already done in the SIG_DFL/SIG_IGN (integer) code path.
This prevents a stale entry in the table if sigaction fails.
close GH-21270
Add missing PCNTL_CPU_DESTROY(mask) call before RETURN_THROWS() when
the cpu id is out of range, matching the cleanup on other error paths.
close GH-21268
Save errno into a local int before calling close(fd), as close() may
clobber errno on failure. Use int rather than errno_t because errno_t
is defined in C11 Annex K (bounds-checking interfaces) which is
optional and not widely implemented — many platforms (Linux/glibc,
musl, macOS, FreeBSD) do not provide it.
close GH-21256
Truncating to an int seems dangerous, esp. in combination with a MIN
macro. I don't see a reason to truncate the length from size_t to int,
and especially no reason to change the signedness.
Closes GH-20747.
In SCCP, arrays containing partial objects must be marked as partial so that
their values are not accidentally propagated.
Fixes GH-21227
Closes GH-21232
This avoids a crash in cases where the list of candidate encodings is so huge
that alloca would fail. Such crashes have been observed when the list of
encodings was larger than around 208,000 entries.
The PHP_PQ_ERROR macro calls php_error_docref() which triggers user error handlers
thus libpq does not have the chance to clean the resources (and empty
connections string are allowed) on failure thus we avoid this macro
and delay the error handling after.
close GH-21165
in the ipv6 address creation helper we need to use, for the error
message, the converted data rather than assuming the original
is a proper zend_string().
close GH-21166
The SysV shared memory allocator in OPcache hardcodes a maximum segment size of
32MB (SEG_ALLOC_SIZE_MAX). If the JIT buffer exceeds this, which it does with
the default 64MB size, startup will fail with "Insufficient shared memory!".
The allocator will now try allocating a contiguous buffer first, and only then
use segmentation by searching for continuously smaller powers of 2.
Fixes GH-20718
Closes GH-20719
There are two issues:
1. The 'e' formatter doesn't output the seconds of the timezone even if
it has seconds.
2. var_dump(), (array) cast, serialization, ... don't include the
timezone second offset in the output. This means that, for example,
serializing and then unserializing a date object loses the seconds of
the timezone. This can be observed by comparing the output of
getTimezone() for `$dt` vs the unserialized object in the provided test.
Closes GH-20764.
The "current" and "end" field also rely on start_ce, which is set by
"start". Therefore, if "current" or "end" are provided, so must "start"
be provided.
Closes GH-20939.
Prior to this patch there was a common read handler, and it relied on
the dom class set in the intern document. However, Dom\Implementation
allows creating DTDs unassociated with a document, so we can't rely on
an intern document and the check fails. This causes the ZVAL_NULL() path
to be taken.
To solve this, just split the handler.
Closes GH-21082.
In a lot of places the return value is not checked, and when the
function fails the code continues execution. However, this means that
operations on the stack fail and will cause memory leaks on the objects
that weren't pushed.
We also notice an inconsistency in how these failures are handled.
For example, in one place we explicitly have a fatal error
`php_error_docref(NULL, E_ERROR, "Memory allocation failure");`
but this is the only place to do so.
Closes GH-20957.
This test still fails on i386 Windows with "Allowed memory size of %d bytes
exhausted" because the output buffer grows too big. My first intuition was to
add a chunk_size to ob_start, but this won't work if the output buffer is
flushed deep into the call stack, causing a premature or just a second stack
limit error. So, reduce the stack size in an attempt to produce less output.
When FE_RESET_RW executes, it converts the CV to a reference before
checking if the array/object is empty. However, when the JIT creates
exit points for FE_RESET_RW in zend_jit_trace_handler(), it wasn't
updating the stack type for op1 to reflect this change.
This caused side traces compiled from these exit points to have
incorrect type information. The side trace's CV cleanup code would
see IS_OBJECT and generate a direct call to zend_objects_store_del(),
but the actual value was a zend_reference*, causing a segfault.
The fix adds ZEND_FE_RESET_RW to the list of opcodes that temporarily
set their op1 stack type to IS_UNKNOWN before creating exit points.
This follows the same pattern used for ZEND_BIND_INIT_STATIC_OR_JMP.
When IS_UNKNOWN, the JIT falls back to SSA type info which correctly
includes MAY_BE_REF for FE_RESET_RW's op1_def.
Fixes GH-20818
Closes GH-20948
This is similar to f6c2e40a11 but for minimal JIT + tracing JIT.
Most of the times the tracing JIT shouldn't rely on going to the VM, but
in some cases, like in minimal JIT, it can and then it hits the same
bug.
Closes GH-20897.
This can trigger the memory limit in run-tests.php, which buffers the tests
output. Instead, only output "nesting level too deep" and discard the rest.
Closes GH-20946
* Fix use-after-free in FE_FREE with GC interaction
When FE_FREE with ZEND_FREE_ON_RETURN frees the loop variable during
an early return from a foreach loop, the live range for the loop
variable was incorrectly extending past the FE_FREE to the normal
loop end. This caused GC to access the already-freed loop variable
when it ran after the RETURN opcode, resulting in use-after-free.
Fix by splitting the ZEND_LIVE_LOOP range when an FE_FREE with
ZEND_FREE_ON_RETURN is encountered:
- One range covers the early return path up to the FE_FREE
- A separate range covers the normal loop end FE_FREE
- Multiple early returns create multiple separate ranges
* Split the live-ranges of loop variables again
b0af9ac733 removed the live-range splitting of foreach variables, however it only added handling to ZEND_HANDLE_EXCEPTION.
This was sort-of elegant, until it was realized in 8258b7731b that it would leak the return variable, requiring some more special handling.
At some point we added live tmpvar rooting in 52cf7ab8a2, but this did not take into account already freed loop variables, which also might happen during ZEND_RETURN, which cannot be trivially accounted for, without even more complicated handling in zend_gc_*_tmpvars() functions.
This commit also proposes a simpler way of tracking the loop end in loopvar freeing ops: handle it directly during live range computation rather than during compilation, eliminating the need for opcache to handle it specifically.
Further, opcache was using live_ranges in its basic block computation in the past, which it no longer does. Thus this complication is no longer necessary and this approach should be actually simpler now.
Closes#20766.
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
---------
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
Co-authored-by: Gustavo Lopes <mail@geleia.net>