From fe064d7f12b908360e990364a6415da5b279fab3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 20 Jan 2024 00:46:34 +0100 Subject: [PATCH] Fix GH-13142: Undefined variable name is shortened when contains \0 Uses the new %S formatter and introduces the necessary changes and helpers. --- NEWS | 2 + Zend/tests/gh13142.phpt | 29 ++++++++++ .../warning_during_heredoc_scan_ahead.phpt | 2 +- Zend/zend.c | 54 ++++++++++--------- Zend/zend.h | 1 + Zend/zend_compile.c | 10 ++-- Zend/zend_execute.c | 4 +- Zend/zend_vm_def.h | 8 +-- Zend/zend_vm_execute.h | 24 ++++----- ext/opcache/jit/zend_jit_helpers.c | 8 +-- ext/opcache/jit/zend_jit_ir.c | 8 +-- ext/standard/array.c | 2 +- main/main.c | 45 ++++++++-------- main/php.h | 1 + 14 files changed, 118 insertions(+), 80 deletions(-) create mode 100644 Zend/tests/gh13142.phpt diff --git a/NEWS b/NEWS index a354e4ceb9a..726b2a7b27f 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Core: Solaris and Haiku. (David Carlier) . Enabled ifunc checks on FreeBSD from the 12.x releases. (Freaky) . Changed the type of PHP_DEBUG and PHP_ZTS constants to bool. (haszi) + . Fixed bug GH-13142 (Undefined variable name is shortened when contains \0). + (nielsdos) Curl: . Deprecated the CURLOPT_BINARYTRANSFER constant. (divinity76) diff --git a/Zend/tests/gh13142.phpt b/Zend/tests/gh13142.phpt new file mode 100644 index 00000000000..15285824ee2 --- /dev/null +++ b/Zend/tests/gh13142.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-13142 (Undefined variable name is shortened when contains \0) +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $test%0test in %s on line %d + +Warning: Undefined variable $%0test in %s on line %d + +Warning: Undefined variable $test%0 in %s on line %d + +Warning: compact(): Undefined variable $a%0b in %s on line %d + +Warning: compact(): Undefined variable $%0ab in %s on line %d + +Warning: compact(): Undefined variable $ab%0 in %s on line %d diff --git a/Zend/tests/warning_during_heredoc_scan_ahead.phpt b/Zend/tests/warning_during_heredoc_scan_ahead.phpt index a0becbb782a..cc6951a0758 100644 --- a/Zend/tests/warning_during_heredoc_scan_ahead.phpt +++ b/Zend/tests/warning_during_heredoc_scan_ahead.phpt @@ -16,4 +16,4 @@ Warning: Octal escape sequence overflow \400 is greater than \377 in %s on line Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d -Warning: Undefined variable $ in %s on line %d +Warning: Undefined variable $%0 in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index fb0af12f9e5..a13884e5516 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1597,26 +1597,22 @@ ZEND_API ZEND_COLD void zend_error_at( va_end(args); } -ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) { - zend_string *filename; - uint32_t lineno; - va_list args; +#define zend_error_impl(type, format) do { \ + zend_string *filename; \ + uint32_t lineno; \ + va_list args; \ + get_filename_lineno(type, &filename, &lineno); \ + va_start(args, format); \ + zend_error_va_list(type, filename, lineno, format, args); \ + va_end(args); \ + } while (0) - get_filename_lineno(type, &filename, &lineno); - va_start(args, format); - zend_error_va_list(type, filename, lineno, format, args); - va_end(args); +ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) { + zend_error_impl(type, format); } ZEND_API ZEND_COLD void zend_error_unchecked(int type, const char *format, ...) { - zend_string *filename; - uint32_t lineno; - va_list args; - - get_filename_lineno(type, &filename, &lineno); - va_start(args, format); - zend_error_va_list(type, filename, lineno, format, args); - va_end(args); + zend_error_impl(type, format); } ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn( @@ -1636,18 +1632,26 @@ ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn( abort(); } +#define zend_error_noreturn_impl(type, format) do { \ + zend_string *filename; \ + uint32_t lineno; \ + va_list args; \ + get_filename_lineno(type, &filename, &lineno); \ + va_start(args, format); \ + zend_error_va_list(type, filename, lineno, format, args); \ + va_end(args); \ + /* Should never reach this. */ \ + abort(); \ + } while (0) + ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) { - zend_string *filename; - uint32_t lineno; - va_list args; + zend_error_noreturn_impl(type, format); +} - get_filename_lineno(type, &filename, &lineno); - va_start(args, format); - zend_error_va_list(type, filename, lineno, format, args); - va_end(args); - /* Should never reach this. */ - abort(); +ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn_unchecked(int type, const char *format, ...) +{ + zend_error_noreturn_impl(type, format); } ZEND_API ZEND_COLD ZEND_NORETURN void zend_strerror_noreturn(int type, int errn, const char *message) diff --git a/Zend/zend.h b/Zend/zend.h index d60da5f83ac..8d23f1b8628 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -345,6 +345,7 @@ extern ZEND_API void (*zend_post_shutdown_cb)(void); ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn_unchecked(int type, const char *format, ...); /* For custom format specifiers like H */ ZEND_API ZEND_COLD void zend_error_unchecked(int type, const char *format, ...); /* If filename is NULL the default filename is used. */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 73ba5899886..c82f2be7712 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4970,7 +4970,7 @@ static void zend_compile_static_var(zend_ast *ast) /* {{{ */ } if (zend_hash_exists(CG(active_op_array)->static_variables, var_name)) { - zend_error_noreturn(E_COMPILE_ERROR, "Duplicate declaration of static variable $%s", ZSTR_VAL(var_name)); + zend_error_noreturn_unchecked(E_COMPILE_ERROR, "Duplicate declaration of static variable $%S", var_name); } zend_eval_const_expr(&ast->child[1]); @@ -7245,8 +7245,8 @@ static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array value = zend_hash_add(op_array->static_variables, var_name, &EG(uninitialized_zval)); if (!value) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot use variable $%s twice", ZSTR_VAL(var_name)); + zend_error_noreturn_unchecked(E_COMPILE_ERROR, + "Cannot use variable $%S twice", var_name); } CG(zend_lineno) = zend_ast_get_lineno(var_name_ast); @@ -7378,8 +7378,8 @@ static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ int i; for (i = 0; i < op_array->last_var; i++) { if (zend_string_equals(op_array->vars[i], var_name)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name)); + zend_error_noreturn_unchecked(E_COMPILE_ERROR, + "Cannot use lexical variable $%S as a parameter name", var_name); } } } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 6311aacb420..de9226c3519 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -272,7 +272,7 @@ static zend_never_inline ZEND_COLD zval* zval_undefined_cv(uint32_t var EXECUTE_ { if (EXPECTED(EG(exception) == NULL)) { zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var)); - zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv)); + zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv); } return &EG(uninitialized_zval); } @@ -3788,7 +3788,7 @@ static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DAT Z_ADDREF_P(result); } else { ZVAL_NULL(result); - zend_error(E_WARNING, "Undefined variable $this"); + zend_error_unchecked(E_WARNING, "Undefined variable $this"); } break; case BP_VAR_IS: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f731653a248..2d12dfbb956 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1755,8 +1755,8 @@ ZEND_VM_C_LABEL(fetch_this): /* Keep name alive in case an error handler tries to free it. */ zend_string_addref(name); } - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -1778,8 +1778,8 @@ ZEND_VM_C_LABEL(fetch_this): } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { ZVAL_NULL(retval); } else { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 41ef6b821d5..c48df8191ef 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -10109,8 +10109,8 @@ fetch_this: /* Keep name alive in case an error handler tries to free it. */ zend_string_addref(name); } - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -10132,8 +10132,8 @@ fetch_this: } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { ZVAL_NULL(retval); } else { @@ -17954,8 +17954,8 @@ fetch_this: /* Keep name alive in case an error handler tries to free it. */ zend_string_addref(name); } - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -17977,8 +17977,8 @@ fetch_this: } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { ZVAL_NULL(retval); } else { @@ -48342,8 +48342,8 @@ fetch_this: /* Keep name alive in case an error handler tries to free it. */ zend_string_addref(name); } - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -48365,8 +48365,8 @@ fetch_this: } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { - zend_error(E_WARNING, "Undefined %svariable $%s", - (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); if (type == BP_VAR_RW && !EG(exception)) { ZVAL_NULL(retval); } else { diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index f439a7572f4..dab251056ba 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -95,7 +95,7 @@ static ZEND_COLD void ZEND_FASTCALL zend_jit_invalid_method_call(zval *object) if (Z_TYPE_P(object) == IS_UNDEF && opline->op1_type == IS_CV) { zend_string *cv = EX(func)->op_array.vars[EX_VAR_TO_NUM(opline->op1.var)]; - zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv)); + zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv); if (UNEXPECTED(EG(exception) != NULL)) { return; } @@ -340,7 +340,7 @@ static int ZEND_FASTCALL zend_jit_undefined_op_helper(uint32_t var) const zend_execute_data *execute_data = EG(current_execute_data); zend_string *cv = EX(func)->op_array.vars[EX_VAR_TO_NUM(var)]; - zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv)); + zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv); return EG(exception) == NULL; } @@ -354,7 +354,7 @@ static int ZEND_FASTCALL zend_jit_undefined_op_helper_write(HashTable *ht, uint3 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { GC_ADDREF(ht); } - zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv)); + zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv); if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { if (!GC_REFCOUNT(ht)) { zend_array_destroy(ht); @@ -2418,7 +2418,7 @@ static void ZEND_FASTCALL zend_jit_invalid_property_incdec(zval *container, cons if (Z_TYPE_P(container) == IS_UNDEF && opline->op1_type == IS_CV) { zend_string *cv = EX(func)->op_array.vars[EX_VAR_TO_NUM(opline->op1.var)]; - zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv)); + zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv); } if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 6c17f932f62..cca3d4b8b0e 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -4646,7 +4646,7 @@ static int zend_jit_inc_dec(zend_jit_ctx *jit, const zend_op *opline, uint32_t o if_def = jit_if_not_Z_TYPE(jit, op1_addr, IS_UNDEF); ir_IF_FALSE_cold(if_def); - // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); + // zend_error_unchecked(E_WARNING, "Undefined variable $%S", CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))); ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(opline->op1.var)); jit_set_Z_TYPE_INFO(jit, op1_def_addr, IS_NULL); @@ -5588,7 +5588,7 @@ static int zend_jit_long_math_helper(zend_jit_ctx *jit, if_def = jit_if_not_Z_TYPE(jit, op1_addr, IS_UNDEF); ir_IF_FALSE_cold(if_def); - // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); + // zend_error_unchecked(E_WARNING, "Undefined variable $%S", CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))); ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(opline->op1.var)); ref2 = jit_EG(uninitialized_zval); @@ -5604,7 +5604,7 @@ static int zend_jit_long_math_helper(zend_jit_ctx *jit, if_def = jit_if_not_Z_TYPE(jit, op2_addr, IS_UNDEF); ir_IF_FALSE_cold(if_def); - // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var)))); + // zend_error_unchecked(E_WARNING, "Undefined variable $%S", CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var))); ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(opline->op2.var)); ref2 = jit_EG(uninitialized_zval); @@ -5980,7 +5980,7 @@ static int zend_jit_simple_assign(zend_jit_ctx *jit, jit_SET_EX_OPLINE(jit, opline); ZEND_ASSERT(Z_MODE(val_addr) == IS_MEM_ZVAL); - // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); + // zend_error_unchecked(E_WARNING, "Undefined variable $%S", CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))); ret = ir_CALL_1(IR_I32, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(Z_OFFSET(val_addr))); if (check_exception) { diff --git a/ext/standard/array.c b/ext/standard/array.c index 388b15a0879..3241d6e0f47 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2608,7 +2608,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } } else { - php_error_docref(NULL, E_WARNING, "Undefined variable $%s", ZSTR_VAL(Z_STR_P(entry))); + php_error_docref_unchecked(NULL, E_WARNING, "Undefined variable $%S", Z_STR_P(entry)); } } else if (Z_TYPE_P(entry) == IS_ARRAY) { if (Z_REFCOUNTED_P(entry)) { diff --git a/main/main.c b/main/main.c index 6633689d85d..b09e9bb9970 100644 --- a/main/main.c +++ b/main/main.c @@ -944,11 +944,10 @@ static zend_string *escape_html(const char *buffer, size_t buffer_len) { */ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args) { - zend_string *replace_buffer = NULL, *replace_origin = NULL; - char *buffer = NULL, *docref_buf = NULL, *target = NULL; + zend_string *replace_origin = NULL; + char *docref_buf = NULL, *target = NULL; char *docref_target = "", *docref_root = ""; char *p; - int buffer_len = 0; const char *space = ""; const char *class_name = ""; const char *function; @@ -958,18 +957,16 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ int is_function = 0; /* get error text into buffer and escape for html if necessary */ - buffer_len = (int)vspprintf(&buffer, 0, format, args); + zend_string *buffer = vstrpprintf(0, format, args); if (PG(html_errors)) { - replace_buffer = escape_html(buffer, buffer_len); - efree(buffer); + zend_string *replace_buffer = escape_html(ZSTR_VAL(buffer), ZSTR_LEN(buffer)); + zend_string_free(buffer); if (replace_buffer) { - buffer = ZSTR_VAL(replace_buffer); - buffer_len = (int)ZSTR_LEN(replace_buffer); + buffer = replace_buffer; } else { - buffer = ""; - buffer_len = 0; + buffer = zend_empty_string; } } @@ -1091,15 +1088,15 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ } /* display html formatted or only show the additional links */ if (PG(html_errors)) { - message = zend_strpprintf(0, "%s [%s]: %s", origin, docref_root, docref, docref_target, docref, buffer); + message = zend_strpprintf_unchecked(0, "%s [%s]: %S", origin, docref_root, docref, docref_target, docref, buffer); } else { - message = zend_strpprintf(0, "%s [%s%s%s]: %s", origin, docref_root, docref, docref_target, buffer); + message = zend_strpprintf_unchecked(0, "%s [%s%s%s]: %S", origin, docref_root, docref, docref_target, buffer); } if (target) { efree(target); } } else { - message = zend_strpprintf(0, "%s: %s", origin, buffer); + message = zend_strpprintf_unchecked(0, "%s: %S", origin, buffer); } if (replace_origin) { zend_string_free(replace_origin); @@ -1110,11 +1107,7 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ efree(docref_buf); } - if (replace_buffer) { - zend_string_free(replace_buffer); - } else { - efree(buffer); - } + zend_string_free(buffer); zend_error_zstr(type, message); zend_string_release(message); @@ -1123,13 +1116,21 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ /* {{{ php_error_docref */ /* Generate an error which links to docref or the php.net documentation if docref is NULL */ +#define php_error_docref_impl(docref, type, format) do {\ + va_list args; \ + va_start(args, format); \ + php_verror(docref, "", type, format, args); \ + va_end(args); \ + } while (0) + PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...) { - va_list args; + php_error_docref_impl(docref, type, format); +} - va_start(args, format); - php_verror(docref, "", type, format, args); - va_end(args); +PHPAPI ZEND_COLD void php_error_docref_unchecked(const char *docref, int type, const char *format, ...) +{ + php_error_docref_impl(docref, type, format); } /* }}} */ diff --git a/main/php.h b/main/php.h index 79b73b68d1f..b10ded010d1 100644 --- a/main/php.h +++ b/main/php.h @@ -328,6 +328,7 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ /* PHPAPI void php_error(int type, const char *format, ...); */ PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); +PHPAPI ZEND_COLD void php_error_docref_unchecked(const char *docref, int type, const char *format, ...); PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 4, 5); PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)