Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
60 changes: 26 additions & 34 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,8 +833,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
#endif
executor_globals->flags = EG_FLAGS_INITIAL;
executor_globals->record_errors = false;
executor_globals->num_errors = 0;
executor_globals->errors = NULL;
memset(&executor_globals->errors, 0, sizeof(executor_globals->errors));
executor_globals->filename_override = NULL;
executor_globals->lineno_override = -1;
#ifdef ZEND_CHECK_STACK_LIMIT
Expand Down Expand Up @@ -1446,8 +1445,7 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
zend_stack delayed_oplines_stack;
int type = orig_type & E_ALL;
bool orig_record_errors;
uint32_t orig_num_errors;
zend_error_info **orig_errors;
zend_err_buf orig_errors_buf;
zend_result res;

/* If we're executing a function during SCCP, count any warnings that may be emitted,
Expand All @@ -1459,11 +1457,9 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
}

/* Emit any delayed error before handling fatal error */
if ((type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL) && EG(num_errors)) {
uint32_t num_errors = EG(num_errors);
zend_error_info **errors = EG(errors);
EG(num_errors) = 0;
EG(errors) = NULL;
if ((type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL) && EG(errors).size) {
zend_err_buf errors_buf = EG(errors);
EG(errors).size = 0;

bool orig_record_errors = EG(record_errors);
EG(record_errors) = false;
Expand All @@ -1473,12 +1469,11 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
int orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting);
EG(user_error_handler_error_reporting) = 0;

zend_emit_recorded_errors_ex(num_errors, errors);
zend_emit_recorded_errors_ex(errors_buf.size, errors_buf.errors);

EG(user_error_handler_error_reporting) = orig_user_error_handler_error_reporting;
EG(record_errors) = orig_record_errors;
EG(num_errors) = num_errors;
EG(errors) = errors;
EG(errors) = errors_buf;
}

if (EG(record_errors)) {
Expand All @@ -1487,12 +1482,13 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
info->lineno = error_lineno;
info->filename = zend_string_copy(error_filename);
info->message = zend_string_copy(message);

/* This is very inefficient for a large number of errors.
* Use pow2 realloc if it becomes a problem. */
EG(num_errors)++;
EG(errors) = erealloc(EG(errors), sizeof(zend_error_info*) * EG(num_errors));
EG(errors)[EG(num_errors)-1] = info;
EG(errors).size++;
if (EG(errors).size > EG(errors).capacity) {
uint32_t capacity = EG(errors).capacity ? EG(errors).capacity + (EG(errors).capacity >> 1) : 2;
EG(errors).errors = erealloc(EG(errors).errors, sizeof(zend_error_info *) * capacity);
EG(errors).capacity = capacity;
}
EG(errors).errors[EG(errors).size - 1] = info;

/* Do not process non-fatal recorded error */
if (!(type & E_FATAL_ERRORS) || (type & E_DONT_BAIL)) {
Expand Down Expand Up @@ -1575,17 +1571,15 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
}

orig_record_errors = EG(record_errors);
orig_num_errors = EG(num_errors);
orig_errors = EG(errors);
EG(record_errors) = false;
EG(num_errors) = 0;
EG(errors) = NULL;

orig_errors_buf = EG(errors);
memset(&EG(errors), 0, sizeof(EG(errors)));

res = call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params);

EG(record_errors) = orig_record_errors;
EG(num_errors) = orig_num_errors;
EG(errors) = orig_errors;
EG(errors) = orig_errors_buf;

if (res == SUCCESS) {
if (Z_TYPE(retval) != IS_UNDEF) {
Expand Down Expand Up @@ -1780,8 +1774,7 @@ ZEND_API void zend_begin_record_errors(void)
{
ZEND_ASSERT(!EG(record_errors) && "Error recording already enabled");
EG(record_errors) = true;
EG(num_errors) = 0;
EG(errors) = NULL;
EG(errors).size = 0;
}

ZEND_API void zend_emit_recorded_errors_ex(uint32_t num_errors, zend_error_info **errors)
Expand All @@ -1795,24 +1788,23 @@ ZEND_API void zend_emit_recorded_errors_ex(uint32_t num_errors, zend_error_info
ZEND_API void zend_emit_recorded_errors(void)
{
EG(record_errors) = false;
zend_emit_recorded_errors_ex(EG(num_errors), EG(errors));
zend_emit_recorded_errors_ex(EG(errors).size, EG(errors).errors);
}

ZEND_API void zend_free_recorded_errors(void)
{
if (!EG(num_errors)) {
if (!EG(errors).size) {
return;
}

for (uint32_t i = 0; i < EG(num_errors); i++) {
zend_error_info *info = EG(errors)[i];
for (uint32_t i = 0; i < EG(errors).size; i++) {
zend_error_info *info = EG(errors).errors[i];
zend_string_release(info->filename);
zend_string_release(info->message);
efree(info);
efree_size(info, sizeof(zend_error_info));
}
efree(EG(errors));
EG(errors) = NULL;
EG(num_errors) = 0;
efree(EG(errors).errors);
memset(&EG(errors), 0, sizeof(EG(errors)));
}

ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
Expand Down
3 changes: 1 addition & 2 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,7 @@ void init_executor(void) /* {{{ */
EG(get_gc_buffer).start = EG(get_gc_buffer).end = EG(get_gc_buffer).cur = NULL;

EG(record_errors) = false;
EG(num_errors) = 0;
EG(errors) = NULL;
memset(&EG(errors), 0, sizeof(EG(errors)));

EG(filename_override) = NULL;
EG(lineno_override) = -1;
Expand Down
10 changes: 8 additions & 2 deletions Zend/zend_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,20 @@ typedef struct _zend_vm_stack *zend_vm_stack;
typedef struct _zend_ini_entry zend_ini_entry;
typedef struct _zend_fiber_context zend_fiber_context;
typedef struct _zend_fiber zend_fiber;
typedef struct _zend_error_info zend_error_info;

typedef enum {
ZEND_MEMOIZE_NONE,
ZEND_MEMOIZE_COMPILE,
ZEND_MEMOIZE_FETCH,
} zend_memoize_mode;

typedef struct zend_err_buf {
uint32_t size;
uint32_t capacity;
zend_error_info **errors;
} zend_err_buf;

struct _zend_compiler_globals {
zend_stack loop_var_stack;

Expand Down Expand Up @@ -298,8 +305,7 @@ struct _zend_executor_globals {
* and their processing is delayed until zend_emit_recorded_errors()
* is called or a fatal diagnostic is emitted. */
bool record_errors;
uint32_t num_errors;
zend_error_info **errors;
zend_err_buf errors;

/* Override filename or line number of thrown errors and exceptions */
zend_string *filename_override;
Expand Down
50 changes: 25 additions & 25 deletions build/gen_stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@ function array_any(array $array, callable $callback): bool {
}
}

if (function_exists('clone')) {
// Replace (\clone)(...) with \clone(...) once the minimally
// supported PHP version is 8.5.
define('clone', \clone(...));
} else {
define(
'clone',
/**
* @template T
* @param T $o
* @return T
*/
function (object $o): object {
return clone $o;
}
);
}

/**
* @return FileInfo[]
*/
Expand Down Expand Up @@ -2184,9 +2202,7 @@ public function toArgInfoCode(?int $minPHPCompatibility): string {

public function __clone()
{
foreach ($this->args as $key => $argInfo) {
$this->args[$key] = clone $argInfo;
}
$this->args = array_map((\clone)(...), $this->args);
$this->return = clone $this->return;
}
}
Expand Down Expand Up @@ -4154,17 +4170,9 @@ private function createIncludeElement(DOMDocument $doc, string $query, int $inde

public function __clone()
{
foreach ($this->constInfos as $key => $constInfo) {
$this->constInfos[$key] = clone $constInfo;
}

foreach ($this->propertyInfos as $key => $propertyInfo) {
$this->propertyInfos[$key] = clone $propertyInfo;
}

foreach ($this->funcInfos as $key => $funcInfo) {
$this->funcInfos[$key] = clone $funcInfo;
}
$this->constInfos = array_map((\clone)(...), $this->constInfos);
$this->propertyInfos = array_map((\clone)(...), $this->propertyInfos);
$this->funcInfos = array_map((\clone)(...), $this->funcInfos);
}

/**
Expand Down Expand Up @@ -4275,17 +4283,9 @@ public function getAllConstInfos(): array {

public function __clone()
{
foreach ($this->constInfos as $key => $constInfo) {
$this->constInfos[$key] = clone $constInfo;
}

foreach ($this->funcInfos as $key => $funcInfo) {
$this->funcInfos[$key] = clone $funcInfo;
}

foreach ($this->classInfos as $key => $classInfo) {
$this->classInfos[$key] = clone $classInfo;
}
$this->constInfos = array_map((\clone)(...), $this->constInfos);
$this->funcInfos = array_map((\clone)(...), $this->funcInfos);
$this->classInfos = array_map((\clone)(...), $this->classInfos);
}

private function getMinimumPhpVersionIdCompatibility(): ?int {
Expand Down
20 changes: 10 additions & 10 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -1968,8 +1968,8 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int

if (persistent_script) {
if (ZCG(accel_directives).record_warnings) {
persistent_script->num_warnings = EG(num_errors);
persistent_script->warnings = EG(errors);
persistent_script->num_warnings = EG(errors).size;
persistent_script->warnings = EG(errors).errors;
}

from_memory = false;
Expand Down Expand Up @@ -2193,8 +2193,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
from_shared_memory = false;
if (persistent_script) {
if (ZCG(accel_directives).record_warnings) {
persistent_script->num_warnings = EG(num_errors);
persistent_script->warnings = EG(errors);
persistent_script->num_warnings = EG(errors).size;
persistent_script->warnings = EG(errors).errors;
}

/* See GH-17246: we disable GC so that user code cannot be executed during the optimizer run. */
Expand Down Expand Up @@ -2421,7 +2421,7 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
}
ZCG(current_persistent_script) = &dummy;
zend_persist_class_entry_calc(ce);
zend_persist_warnings_calc(EG(num_errors), EG(errors));
zend_persist_warnings_calc(EG(errors).size, EG(errors).errors);
size = dummy.size;

zend_shared_alloc_clear_xlat_table();
Expand Down Expand Up @@ -2491,8 +2491,8 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
JIT_G(on) = jit_on_old;
#endif

entry->num_warnings = EG(num_errors);
entry->warnings = zend_persist_warnings(EG(num_errors), EG(errors));
entry->num_warnings = EG(errors).size;
entry->warnings = zend_persist_warnings(EG(errors).size, EG(errors).errors);
entry->next = proto->inheritance_cache;
proto->inheritance_cache = entry;

Expand Down Expand Up @@ -4123,9 +4123,9 @@ static void preload_link(void)
/* Remember the last error. */
zend_error_cb = orig_error_cb;
EG(record_errors) = false;
ZEND_ASSERT(EG(num_errors) > 0);
zend_hash_update_ptr(&errors, key, EG(errors)[EG(num_errors)-1]);
EG(num_errors)--;
ZEND_ASSERT(EG(errors).size > 0);
zend_hash_update_ptr(&errors, key, EG(errors).errors[EG(errors).size-1]);
EG(errors).size--;
} zend_end_try();
CG(in_compilation) = false;
CG(compiled_filename) = NULL;
Expand Down