From 773f980e00af7ca45488d3c2879f5f6ba78c96e2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 1 Oct 2020 13:18:21 +0300 Subject: [PATCH 01/31] Backport of a partial fix for bug Bug #76982 (memory leak declaring closure in included file). --- Zend/zend_closures.c | 5 ++++- Zend/zend_vm_def.h | 9 --------- Zend/zend_vm_execute.h | 9 --------- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index b9d8bd1c75015..022df9dabe52d 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -666,6 +666,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent if (func->type == ZEND_USER_FUNCTION) { memcpy(&closure->func, func, sizeof(zend_op_array)); closure->func.common.fn_flags |= ZEND_ACC_CLOSURE; + closure->func.common.fn_flags &= ~ZEND_ACC_IMMUTABLE; if (closure->func.op_array.static_variables) { closure->func.op_array.static_variables = zend_array_dup(closure->func.op_array.static_variables); @@ -676,7 +677,9 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent || func->common.scope != scope || (func->common.fn_flags & ZEND_ACC_NO_RT_ARENA) ) { - if (!func->op_array.run_time_cache && (func->common.fn_flags & ZEND_ACC_CLOSURE)) { + if (!func->op_array.run_time_cache + && (func->common.fn_flags & ZEND_ACC_CLOSURE) + && !(func->common.fn_flags & ZEND_ACC_IMMUTABLE)) { /* If a real closure is used for the first time, we create a shared runtime cache * and remember which scope it is for. */ func->common.scope = scope; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6f9aca4b55166..1b4eb5720dd1c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7097,15 +7097,6 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1); ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION); - fbc = Z_PTR_P(zfunc); - if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) { - zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); - - memcpy(new_func, fbc, sizeof(zend_op_array)); - new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE; - Z_PTR_P(zfunc) = fbc = new_func; - } - if (Z_TYPE(EX(This)) == IS_OBJECT) { called_scope = Z_OBJCE(EX(This)); if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) || diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e5e5a9e1da89e..be8b2b3a1f2aa 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -9209,15 +9209,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1); ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION); - fbc = Z_PTR_P(zfunc); - if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) { - zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); - - memcpy(new_func, fbc, sizeof(zend_op_array)); - new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE; - Z_PTR_P(zfunc) = fbc = new_func; - } - if (Z_TYPE(EX(This)) == IS_OBJECT) { called_scope = Z_OBJCE(EX(This)); if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) || From 0a84fba0deb1c1b75770a436c4236dc56e6d0463 Mon Sep 17 00:00:00 2001 From: Dik Takken Date: Thu, 24 Sep 2020 12:06:06 +0200 Subject: [PATCH 02/31] Improve parameter names in ext/xmlwriter Closes GH-6202. --- ext/xmlwriter/php_xmlwriter.stub.php | 92 +++++++++++++-------------- ext/xmlwriter/php_xmlwriter_arginfo.h | 72 ++++++++++----------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/ext/xmlwriter/php_xmlwriter.stub.php b/ext/xmlwriter/php_xmlwriter.stub.php index 897fe13b875a7..981cadda85836 100644 --- a/ext/xmlwriter/php_xmlwriter.stub.php +++ b/ext/xmlwriter/php_xmlwriter.stub.php @@ -6,85 +6,85 @@ function xmlwriter_open_uri(string $uri): XMLWriter|false {} function xmlwriter_open_memory(): XMLWriter|false {} -function xmlwriter_set_indent(XMLWriter $xmlwriter, bool $indent): bool {} +function xmlwriter_set_indent(XMLWriter $writer, bool $enable): bool {} -function xmlwriter_set_indent_string(XMLWriter $xmlwriter, string $indentString): bool {} +function xmlwriter_set_indent_string(XMLWriter $writer, string $indentation): bool {} -function xmlwriter_start_comment(XMLWriter $xmlwriter): bool {} +function xmlwriter_start_comment(XMLWriter $writer): bool {} -function xmlwriter_end_comment(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_comment(XMLWriter $writer): bool {} -function xmlwriter_start_attribute(XMLWriter $xmlwriter, string $name): bool {} +function xmlwriter_start_attribute(XMLWriter $writer, string $name): bool {} -function xmlwriter_end_attribute(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_attribute(XMLWriter $writer): bool {} -function xmlwriter_write_attribute(XMLWriter $xmlwriter, string $name, string $value): bool {} +function xmlwriter_write_attribute(XMLWriter $writer, string $name, string $value): bool {} -function xmlwriter_start_attribute_ns(XMLWriter $xmlwriter, ?string $prefix, string $name, ?string $uri): bool {} +function xmlwriter_start_attribute_ns(XMLWriter $writer, ?string $prefix, string $name, ?string $uri): bool {} -function xmlwriter_write_attribute_ns(XMLWriter $xmlwriter, ?string $prefix, string $name, ?string $uri, string $content): bool {} +function xmlwriter_write_attribute_ns(XMLWriter $writer, ?string $prefix, string $name, ?string $uri, string $value): bool {} -function xmlwriter_start_element(XMLWriter $xmlwriter, string $name): bool {} +function xmlwriter_start_element(XMLWriter $writer, string $name): bool {} -function xmlwriter_end_element(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_element(XMLWriter $writer): bool {} -function xmlwriter_full_end_element(XMLWriter $xmlwriter): bool {} +function xmlwriter_full_end_element(XMLWriter $writer): bool {} -function xmlwriter_start_element_ns(XMLWriter $xmlwriter, ?string $prefix, string $name, ?string $uri): bool {} +function xmlwriter_start_element_ns(XMLWriter $writer, ?string $prefix, string $name, ?string $uri): bool {} -function xmlwriter_write_element(XMLWriter $xmlwriter, string $name, ?string $content = null): bool {} +function xmlwriter_write_element(XMLWriter $writer, string $name, ?string $content = null): bool {} -function xmlwriter_write_element_ns(XMLWriter $xmlwriter, ?string $prefix, string $name, ?string $uri, ?string $content = null): bool {} +function xmlwriter_write_element_ns(XMLWriter $writer, ?string $prefix, string $name, ?string $uri, ?string $content = null): bool {} -function xmlwriter_start_pi(XMLWriter $xmlwriter, string $target): bool {} +function xmlwriter_start_pi(XMLWriter $writer, string $target): bool {} -function xmlwriter_end_pi(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_pi(XMLWriter $writer): bool {} -function xmlwriter_write_pi(XMLWriter $xmlwriter, string $target, string $content): bool {} +function xmlwriter_write_pi(XMLWriter $writer, string $target, string $content): bool {} -function xmlwriter_start_cdata(XMLWriter $xmlwriter): bool {} +function xmlwriter_start_cdata(XMLWriter $writer): bool {} -function xmlwriter_end_cdata(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_cdata(XMLWriter $writer): bool {} -function xmlwriter_write_cdata(XMLWriter $xmlwriter, string $content): bool {} +function xmlwriter_write_cdata(XMLWriter $writer, string $content): bool {} -function xmlwriter_text(XMLWriter $xmlwriter, string $content): bool {} +function xmlwriter_text(XMLWriter $writer, string $content): bool {} -function xmlwriter_write_raw(XMLWriter $xmlwriter, string $content): bool {} +function xmlwriter_write_raw(XMLWriter $writer, string $content): bool {} -function xmlwriter_start_document(XMLWriter $xmlwriter, ?string $version = "1.0", ?string $encoding = null, ?string $standalone = null): bool {} +function xmlwriter_start_document(XMLWriter $writer, ?string $version = "1.0", ?string $encoding = null, ?string $standalone = null): bool {} -function xmlwriter_end_document(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_document(XMLWriter $writer): bool {} -function xmlwriter_write_comment(XMLWriter $xmlwriter, string $content): bool {} +function xmlwriter_write_comment(XMLWriter $writer, string $content): bool {} -function xmlwriter_start_dtd(XMLWriter $xmlwriter, string $qualifiedName, ?string $publicId = null, ?string $systemId = null): bool {} +function xmlwriter_start_dtd(XMLWriter $writer, string $qualifiedName, ?string $publicId = null, ?string $systemId = null): bool {} -function xmlwriter_end_dtd(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_dtd(XMLWriter $writer): bool {} -function xmlwriter_write_dtd(XMLWriter $xmlwriter, string $name, ?string $publicId = null, ?string $systemId = null, ?string $subset = null): bool {} +function xmlwriter_write_dtd(XMLWriter $writer, string $name, ?string $publicId = null, ?string $systemId = null, ?string $content = null): bool {} -function xmlwriter_start_dtd_element(XMLWriter $xmlwriter, string $qualifiedName): bool {} +function xmlwriter_start_dtd_element(XMLWriter $writer, string $qualifiedName): bool {} -function xmlwriter_end_dtd_element(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_dtd_element(XMLWriter $writer): bool {} -function xmlwriter_write_dtd_element(XMLWriter $xmlwriter, string $name, string $content): bool {} +function xmlwriter_write_dtd_element(XMLWriter $writer, string $name, string $content): bool {} -function xmlwriter_start_dtd_attlist(XMLWriter $xmlwriter, string $name): bool {} +function xmlwriter_start_dtd_attlist(XMLWriter $writer, string $name): bool {} -function xmlwriter_end_dtd_attlist(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_dtd_attlist(XMLWriter $writer): bool {} -function xmlwriter_write_dtd_attlist(XMLWriter $xmlwriter, string $name, string $content): bool {} +function xmlwriter_write_dtd_attlist(XMLWriter $writer, string $name, string $content): bool {} -function xmlwriter_start_dtd_entity(XMLWriter $xmlwriter, string $name, bool $isparam): bool {} +function xmlwriter_start_dtd_entity(XMLWriter $writer, string $name, bool $isParam): bool {} -function xmlwriter_end_dtd_entity(XMLWriter $xmlwriter): bool {} +function xmlwriter_end_dtd_entity(XMLWriter $writer): bool {} -function xmlwriter_write_dtd_entity(XMLWriter $xmlwriter, string $name, string $content, bool $isparam = false, ?string $publicId = null, ?string $systemId = null, ?string $ndataid = null): bool {} +function xmlwriter_write_dtd_entity(XMLWriter $writer, string $name, string $content, bool $isParam = false, ?string $publicId = null, ?string $systemId = null, ?string $notationData = null): bool {} -function xmlwriter_output_memory(XMLWriter $xmlwriter, bool $flush = true): string {} +function xmlwriter_output_memory(XMLWriter $writer, bool $flush = true): string {} -function xmlwriter_flush(XMLWriter $xmlwriter, bool $empty = true): string|int {} +function xmlwriter_flush(XMLWriter $writer, bool $empty = true): string|int {} class XMLWriter { @@ -95,10 +95,10 @@ public function openUri(string $uri): bool {} public function openMemory(): bool {} /** @alias xmlwriter_set_indent */ - public function setIndent(bool $indent): bool {} + public function setIndent(bool $enable): bool {} /** @alias xmlwriter_set_indent_string */ - public function setIndentString(string $indentString): bool {} + public function setIndentString(string $indentation): bool {} /** @alias xmlwriter_start_comment */ public function startComment(): bool {} @@ -119,7 +119,7 @@ public function writeAttribute(string $name, string $value): bool {} public function startAttributeNs(?string $prefix, string $name, ?string $uri): bool {} /** @alias xmlwriter_write_attribute_ns */ - public function writeAttributeNs(?string $prefix, string $name, ?string $uri, string $content): bool {} + public function writeAttributeNs(?string $prefix, string $name, ?string $uri, string $value): bool {} /** @alias xmlwriter_start_element */ public function startElement(string $name): bool {} @@ -179,7 +179,7 @@ public function startDtd(string $qualifiedName, ?string $publicId = null, ?strin public function endDtd(): bool {} /** @alias xmlwriter_write_dtd */ - public function writeDtd(string $name, ?string $publicId = null, ?string $systemId = null, ?string $subset = null): bool {} + public function writeDtd(string $name, ?string $publicId = null, ?string $systemId = null, ?string $content = null): bool {} /** @alias xmlwriter_start_dtd_element */ public function startDtdElement(string $qualifiedName): bool {} @@ -200,13 +200,13 @@ public function endDtdAttlist(): bool {} public function writeDtdAttlist(string $name, string $content): bool {} /** @alias xmlwriter_start_dtd_entity */ - public function startDtdEntity(string $name, bool $isparam): bool {} + public function startDtdEntity(string $name, bool $isParam): bool {} /** @alias xmlwriter_end_dtd_entity */ public function endDtdEntity(): bool {} /** @alias xmlwriter_write_dtd_entity */ - public function writeDtdEntity(string $name, string $content, bool $isparam = false, ?string $publicId = null, ?string $systemId = null, ?string $ndataid = null): bool {} + public function writeDtdEntity(string $name, string $content, bool $isParam = false, ?string $publicId = null, ?string $systemId = null, ?string $notationData = null): bool {} /** @alias xmlwriter_output_memory */ public function outputMemory(bool $flush = true): string {} diff --git a/ext/xmlwriter/php_xmlwriter_arginfo.h b/ext/xmlwriter/php_xmlwriter_arginfo.h index 39597b4b826d1..2d5bccdb42ce6 100644 --- a/ext/xmlwriter/php_xmlwriter_arginfo.h +++ b/ext/xmlwriter/php_xmlwriter_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b1a8634bf79e1ac8fb94611ab942e9e4c06636f9 */ + * Stub hash: d265aff62d6dcd195c65e6205cc4cac063f5f237 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_xmlwriter_open_uri, 0, 1, XMLWriter, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) @@ -9,47 +9,47 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_xmlwriter_open_memory, 0, 0, ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_set_indent, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) - ZEND_ARG_TYPE_INFO(0, indent, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) + ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_set_indent_string, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) - ZEND_ARG_TYPE_INFO(0, indentString, IS_STRING, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) + ZEND_ARG_TYPE_INFO(0, indentation, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_comment, 0, 1, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_comment arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_attribute, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_attribute arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_attribute, 0, 3, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_attribute_ns, 0, 4, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 1) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_attribute_ns, 0, 5, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 1) - ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_start_element arginfo_xmlwriter_start_attribute @@ -61,13 +61,13 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_start_element_ns arginfo_xmlwriter_start_attribute_ns ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_element, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, content, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_element_ns, 0, 4, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 1) @@ -75,14 +75,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_element_ns, 0, 4 ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_pi, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, target, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_pi arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_pi, 0, 3, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, target, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -92,7 +92,7 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_cdata arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_cdata, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -101,7 +101,7 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_write_raw arginfo_xmlwriter_write_cdata ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_document, 0, 1, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, version, IS_STRING, 1, "\"1.0\"") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, standalone, IS_STRING, 1, "null") @@ -112,7 +112,7 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_write_comment arginfo_xmlwriter_write_cdata ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_dtd, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, publicId, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, systemId, IS_STRING, 1, "null") @@ -121,22 +121,22 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_dtd arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_dtd, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, publicId, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, systemId, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, subset, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, content, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_dtd_element, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_dtd_element arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_dtd_element, 0, 3, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -148,30 +148,30 @@ ZEND_END_ARG_INFO() #define arginfo_xmlwriter_write_dtd_attlist arginfo_xmlwriter_write_dtd_element ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_dtd_entity, 0, 3, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, isparam, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, isParam, _IS_BOOL, 0) ZEND_END_ARG_INFO() #define arginfo_xmlwriter_end_dtd_entity arginfo_xmlwriter_start_comment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_write_dtd_entity, 0, 3, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isparam, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isParam, _IS_BOOL, 0, "false") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, publicId, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, systemId, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ndataid, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, notationData, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_output_memory, 0, 1, IS_STRING, 0) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flush, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_xmlwriter_flush, 0, 1, MAY_BE_STRING|MAY_BE_LONG) - ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0) + ZEND_ARG_OBJ_INFO(0, writer, XMLWriter, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, empty, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() @@ -183,11 +183,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_openMemory, 0, 0 ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_setIndent, 0, 1, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, indent, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_setIndentString, 0, 1, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, indentString, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, indentation, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_class_XMLWriter_startComment arginfo_class_XMLWriter_openMemory @@ -215,7 +215,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_writeAttributeNs ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 1) - ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_class_XMLWriter_startElement arginfo_class_XMLWriter_startAttribute @@ -283,7 +283,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_writeDtd, 0, 1, ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, publicId, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, systemId, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, subset, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, content, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_startDtdElement, 0, 1, _IS_BOOL, 0) @@ -305,7 +305,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_startDtdEntity, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, isparam, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, isParam, _IS_BOOL, 0) ZEND_END_ARG_INFO() #define arginfo_class_XMLWriter_endDtdEntity arginfo_class_XMLWriter_openMemory @@ -313,10 +313,10 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_writeDtdEntity, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isparam, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isParam, _IS_BOOL, 0, "false") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, publicId, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, systemId, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ndataid, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, notationData, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_XMLWriter_outputMemory, 0, 0, IS_STRING, 0) From afab9eb48c883766b7870f76f2e2b0a4bd575786 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Oct 2020 16:12:56 +0200 Subject: [PATCH 03/31] Fix bug #65387 Add GC support to dual_it. This is still missing AppendIterator support. --- NEWS | 3 +++ ext/spl/spl_iterators.c | 47 ++++++++++++++++++++++++++++++++ ext/spl/tests/bug65387.phpt | 54 +++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 ext/spl/tests/bug65387.phpt diff --git a/NEWS b/NEWS index b5f816a055e57..57892d8bb6dbf 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.0.0rc2 +- SPL. + . Fixed bug #65387 (Circular references in SPL iterators are not garbage + collected). (Nikita) 01 Oct 2020, PHP 8.0.0rc1 diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 4735a257a89e7..c73134e9ae06e 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2119,6 +2119,52 @@ static void spl_dual_it_free_storage(zend_object *_object) } /* }}} */ +static HashTable *spl_dual_it_get_gc(zend_object *obj, zval **table, int *n) +{ + spl_dual_it_object *object = spl_dual_it_from_obj(obj); + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + if (!Z_ISUNDEF(object->inner.zobject)) { + zend_get_gc_buffer_add_zval(gc_buffer, &object->inner.zobject); + } + + switch (object->dit_type) { + case DIT_Unknown: + case DIT_Default: + case DIT_IteratorIterator: + case DIT_NoRewindIterator: + case DIT_InfiniteIterator: + case DIT_LimitIterator: + case DIT_RegexIterator: + case DIT_RecursiveRegexIterator: + /* Nothing to do */ + break; + case DIT_AppendIterator: + // TODO + /*zend_get_gc_buffer_add_obj(gc_buffer, &object->u.append.iterator->std); + if (Z_TYPE(object->u.append.zarrayit) != IS_UNDEF) { + zend_get_gc_buffer_add_zval(gc_buffer, &object->u.append.zarrayit); + }*/ + break; + case DIT_CachingIterator: + case DIT_RecursiveCachingIterator: + zend_get_gc_buffer_add_zval(gc_buffer, &object->u.caching.zcache); + break; + case DIT_CallbackFilterIterator: + case DIT_RecursiveCallbackFilterIterator: + if (object->u.cbfilter) { + zend_get_gc_buffer_add_zval(gc_buffer, &object->u.cbfilter->fci.function_name); + if (object->u.cbfilter->fci.object) { + zend_get_gc_buffer_add_obj(gc_buffer, object->u.cbfilter->fci.object); + } + } + break; + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + return zend_std_get_properties(obj); +} + /* {{{ spl_dual_it_new */ static zend_object *spl_dual_it_new(zend_class_entry *class_type) { @@ -3191,6 +3237,7 @@ PHP_MINIT_FUNCTION(spl_iterators) spl_handlers_dual_it.clone_obj = NULL; spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor; spl_handlers_dual_it.free_obj = spl_dual_it_free_storage; + spl_handlers_dual_it.get_gc = spl_dual_it_get_gc; spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator; diff --git a/ext/spl/tests/bug65387.phpt b/ext/spl/tests/bug65387.phpt new file mode 100644 index 0000000000000..75678254bdfa1 --- /dev/null +++ b/ext/spl/tests/bug65387.phpt @@ -0,0 +1,54 @@ +--TEST-- +Bug #67387: Circular references in SPL iterators are not garbage collected +--FILE-- +it = new CallbackFilterIterator($it, function($elem) { + return true; + }); + } +}; + +// Recursive callback +$it = new RecursiveArrayIterator([1, 2, 3]); +$it2 = new RecursiveCallbackFilterIterator($it, function($elem) use(&$it2) { + return true; +}); + +// Cache +$it = new ArrayIterator(); +$it2 = new CachingIterator($it, CachingIterator::FULL_CACHE); +$it2[] = $it2; +$it2->next(); + +// Recursive cache +$it = new RecursiveArrayIterator(); +$it2 = new RecursiveCachingIterator($it, CachingIterator::FULL_CACHE); +$it2[] = $it2; +$it2->next(); + +// Append +/* TODO +$it = new ArrayIterator(); +$it2 = new AppendIterator(); +$it[] = $it2; +$it2->append($it); + */ + +?> +===DONE=== +--EXPECT-- +===DONE=== From 2c1b5c43656336b6a19070a3529c411084f0304f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Oct 2020 16:18:23 +0200 Subject: [PATCH 04/31] Support GC for AppendIterator This also requires adding GC support for ArrayIterator internal iterators. --- ext/spl/spl_array.c | 9 ++++++++- ext/spl/spl_iterators.c | 5 ++--- ext/spl/tests/bug65387.phpt | 2 -- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index fb23939ca24c8..75668e2f0fc9a 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1079,6 +1079,13 @@ static void spl_array_it_rewind(zend_object_iterator *iter) /* {{{ */ } /* }}} */ +static HashTable *spl_array_it_get_gc(zend_object_iterator *iter, zval **table, int *n) +{ + *n = 1; + *table = &iter->data; + return NULL; +} + /* {{{ spl_array_set_array */ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *array, zend_long ar_flags, int just_array) { if (Z_TYPE_P(array) != IS_OBJECT && Z_TYPE_P(array) != IS_ARRAY) { @@ -1135,7 +1142,7 @@ static const zend_object_iterator_funcs spl_array_it_funcs = { spl_array_it_move_forward, spl_array_it_rewind, NULL, - NULL, /* get_gc */ + spl_array_it_get_gc, }; zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index c73134e9ae06e..40538cda8eec9 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2140,11 +2140,10 @@ static HashTable *spl_dual_it_get_gc(zend_object *obj, zval **table, int *n) /* Nothing to do */ break; case DIT_AppendIterator: - // TODO - /*zend_get_gc_buffer_add_obj(gc_buffer, &object->u.append.iterator->std); + zend_get_gc_buffer_add_obj(gc_buffer, &object->u.append.iterator->std); if (Z_TYPE(object->u.append.zarrayit) != IS_UNDEF) { zend_get_gc_buffer_add_zval(gc_buffer, &object->u.append.zarrayit); - }*/ + } break; case DIT_CachingIterator: case DIT_RecursiveCachingIterator: diff --git a/ext/spl/tests/bug65387.phpt b/ext/spl/tests/bug65387.phpt index 75678254bdfa1..a5b028954ccea 100644 --- a/ext/spl/tests/bug65387.phpt +++ b/ext/spl/tests/bug65387.phpt @@ -41,12 +41,10 @@ $it2[] = $it2; $it2->next(); // Append -/* TODO $it = new ArrayIterator(); $it2 = new AppendIterator(); $it[] = $it2; $it2->append($it); - */ ?> ===DONE=== From 7af24eaedd310911940643d7a5f412393b973389 Mon Sep 17 00:00:00 2001 From: Christian Schneider Date: Wed, 30 Sep 2020 16:52:04 +0200 Subject: [PATCH 05/31] Allow empty needle in grapheme_str*pos, grapheme_str*str For consistency with str* and mb_str* functions. Closes GH-6245. Closes php/php-tasks#20. --- ext/intl/grapheme/grapheme_string.c | 25 ------ ext/intl/grapheme/grapheme_util.c | 11 +++ ext/intl/tests/grapheme_empty.phpt | 124 +++++++++++----------------- 3 files changed, 59 insertions(+), 101 deletions(-) diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index e45330e15085e..7d8df14d2e807 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -124,11 +124,6 @@ PHP_FUNCTION(grapheme_strpos) /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - if (needle_len == 0) { - zend_argument_value_error(2, "cannot be empty"); - RETURN_THROWS(); - } - if (offset >= 0 && grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0) { /* quick check to see if the string might be there * I realize that 'offset' is 'grapheme count offset' but will work in spite of that @@ -178,11 +173,6 @@ PHP_FUNCTION(grapheme_stripos) /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - if (needle_len == 0) { - zend_argument_value_error(2, "cannot be empty"); - RETURN_THROWS(); - } - is_ascii = ( grapheme_ascii_check((unsigned char*)haystack, haystack_len) >= 0 ); if ( is_ascii ) { @@ -244,11 +234,6 @@ PHP_FUNCTION(grapheme_strrpos) /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - if (needle_len == 0) { - zend_argument_value_error(2, "cannot be empty"); - RETURN_THROWS(); - } - is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; if ( is_ascii ) { @@ -304,11 +289,6 @@ PHP_FUNCTION(grapheme_strripos) /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - if (needle_len == 0) { - zend_argument_value_error(2, "cannot be empty"); - RETURN_THROWS(); - } - is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; if ( is_ascii ) { @@ -572,11 +552,6 @@ static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_cas RETURN_THROWS(); } - if (needle_len == 0) { - zend_argument_value_error(2, "cannot be empty"); - RETURN_THROWS(); - } - if ( !f_ignore_case ) { /* ASCII optimization: quick check to see if the string might be there */ diff --git a/ext/intl/grapheme/grapheme_util.c b/ext/intl/grapheme/grapheme_util.c index 8633fddf5bc10..2625a93263e87 100644 --- a/ext/intl/grapheme/grapheme_util.c +++ b/ext/intl/grapheme/grapheme_util.c @@ -126,6 +126,17 @@ int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, ubrk_setText(bi, uhaystack, uhaystack_len, &status); STRPOS_CHECK_STATUS(status, "Failed to set up iterator"); + if (uneedle_len == 0) { + offset_pos = grapheme_get_haystack_offset(bi, last && offset >= 0 ? uhaystack_len : offset); + if (offset_pos == -1) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + ret_pos = -1; + goto finish; + } + ret_pos = offset_pos; + goto finish; + } + status = U_ZERO_ERROR; src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, "", bi, &status); STRPOS_CHECK_STATUS(status, "Error creating search object"); diff --git a/ext/intl/tests/grapheme_empty.phpt b/ext/intl/tests/grapheme_empty.phpt index 31b3d8cc4393f..873abf624e2f4 100644 --- a/ext/intl/tests/grapheme_empty.phpt +++ b/ext/intl/tests/grapheme_empty.phpt @@ -7,82 +7,54 @@ Test grapheme_strpos-alike functions with empty needle ini_set("intl.error_level", E_WARNING); -try { - var_dump(grapheme_strpos("abc", "", -1)); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strpos("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strpos("abc", "", -1)); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_stripos("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_stripos("abc", "", -1)); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strrpos("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strrpos("abc", "", -1)); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strripos("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strripos("abc", "", 1)); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_strstr("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} - -try { - var_dump(grapheme_stristr("abc", "")); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} +var_dump(grapheme_strpos("abc", "")); +var_dump(grapheme_strpos("abc", "", -1)); +var_dump(grapheme_stripos("abc", "")); +var_dump(grapheme_stripos("abc", "", -1)); +var_dump(grapheme_strrpos("abc", "")); +var_dump(grapheme_strrpos("abc", "", -1)); +var_dump(grapheme_strripos("abc", "")); +var_dump(grapheme_strripos("abc", "", 1)); +var_dump(grapheme_strstr("abc", "")); +var_dump(grapheme_strstr("abc", "", true)); +var_dump(grapheme_stristr("abc", "")); +var_dump(grapheme_stristr("abc", "", true)); +var_dump(grapheme_strpos("äbc", "")); +var_dump(grapheme_strpos("äbc", "", -1)); +var_dump(grapheme_stripos("äbc", "")); +var_dump(grapheme_stripos("äbc", "", -1)); +var_dump(grapheme_strrpos("äbc", "")); +var_dump(grapheme_strrpos("äbc", "", -1)); +var_dump(grapheme_strripos("äbc", "")); +var_dump(grapheme_strripos("äbc", "", 1)); +var_dump(grapheme_strstr("äbc", "")); +var_dump(grapheme_strstr("äbc", "", true)); +var_dump(grapheme_stristr("äbc", "")); +var_dump(grapheme_stristr("äbc", "", true)); ?> --EXPECT-- -grapheme_strpos(): Argument #2 ($needle) cannot be empty -grapheme_strpos(): Argument #2 ($needle) cannot be empty -grapheme_strpos(): Argument #2 ($needle) cannot be empty -grapheme_stripos(): Argument #2 ($needle) cannot be empty -grapheme_stripos(): Argument #2 ($needle) cannot be empty -grapheme_strrpos(): Argument #2 ($needle) cannot be empty -grapheme_strrpos(): Argument #2 ($needle) cannot be empty -grapheme_strripos(): Argument #2 ($needle) cannot be empty -grapheme_strripos(): Argument #2 ($needle) cannot be empty -grapheme_strstr(): Argument #2 ($needle) cannot be empty -grapheme_stristr(): Argument #2 ($needle) cannot be empty +int(0) +int(2) +int(0) +int(2) +int(3) +int(2) +int(3) +int(3) +string(3) "abc" +string(0) "" +string(3) "abc" +string(0) "" +int(0) +int(2) +int(0) +int(2) +int(3) +int(2) +int(3) +int(3) +string(4) "äbc" +string(0) "" +string(4) "äbc" +string(0) "" From f82414e935c18c1ff45ef1f006e24220631f5717 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Oct 2020 16:41:51 +0200 Subject: [PATCH 06/31] Fix out of bounds offset handling with empty needle For strrpos with positive out of bounds offsets was not detected. --- ext/intl/grapheme/grapheme_util.c | 4 +- ext/intl/tests/grapheme_out_of_bounds.phpt | 52 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/ext/intl/grapheme/grapheme_util.c b/ext/intl/grapheme/grapheme_util.c index 2625a93263e87..55fa009f56590 100644 --- a/ext/intl/grapheme/grapheme_util.c +++ b/ext/intl/grapheme/grapheme_util.c @@ -127,13 +127,13 @@ int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, STRPOS_CHECK_STATUS(status, "Failed to set up iterator"); if (uneedle_len == 0) { - offset_pos = grapheme_get_haystack_offset(bi, last && offset >= 0 ? uhaystack_len : offset); + offset_pos = grapheme_get_haystack_offset(bi, offset); if (offset_pos == -1) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); ret_pos = -1; goto finish; } - ret_pos = offset_pos; + ret_pos = last && offset >= 0 ? uhaystack_len : offset_pos; goto finish; } diff --git a/ext/intl/tests/grapheme_out_of_bounds.phpt b/ext/intl/tests/grapheme_out_of_bounds.phpt index e563096d7e87b..831ab8740840b 100644 --- a/ext/intl/tests/grapheme_out_of_bounds.phpt +++ b/ext/intl/tests/grapheme_out_of_bounds.phpt @@ -118,6 +118,49 @@ try { } echo "\n"; +// Empty needle + out of bounds +try { + var_dump(grapheme_strpos("äöü", "", 4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_stripos("äöü", "", 4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_strrpos("äöü", "", 4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_strripos("äöü", "", 4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_strpos("äöü", "", -4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_stripos("äöü", "", -4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_strrpos("äöü", "", -4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(grapheme_strripos("äöü", "", -4)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +echo "\n"; + var_dump(grapheme_substr("foo", 3)); var_dump(grapheme_substr("foo", -3)); var_dump(grapheme_substr("foo", 4)); @@ -181,6 +224,15 @@ grapheme_stripos(): Argument #3 ($offset) must be contained in argument #1 ($hay grapheme_strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) grapheme_strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +grapheme_strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) + string(0) "" string(3) "foo" string(0) "" From d96219c185e68c82beb994db2c93bd26f47ce16a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Oct 2020 17:05:23 +0200 Subject: [PATCH 07/31] Fixed bug #80121 The issue affected both CurlHandle and CurlMultiHandle. I'll have to double check this for other resource->object conversions as well. --- NEWS | 4 ++++ ext/curl/interface.c | 14 +++++++++----- ext/curl/multi.c | 6 ++++++ ext/curl/tests/bug80121.phpt | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 ext/curl/tests/bug80121.phpt diff --git a/NEWS b/NEWS index 57892d8bb6dbf..dc39e99d07f01 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.0.0rc2 +- Curl: + . Fixed bug #80121 (Null pointer deref if CurlHandle directly instantiated). + (Nikita) + - SPL. . Fixed bug #65387 (Circular references in SPL iterators are not garbage collected). (Nikita) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 150f98d46fe81..8ff3e0f37471f 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -3308,6 +3308,12 @@ static void curl_free_obj(zend_object *object) fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); #endif + if (!ch->cp) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&ch->std); + return; + } + _php_curl_verify_handlers(ch, 0); /* @@ -3321,12 +3327,10 @@ static void curl_free_obj(zend_object *object) * * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 */ - if (ch->cp != NULL) { - curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); - curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); - curl_easy_cleanup(ch->cp); - } + curl_easy_cleanup(ch->cp); /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 2c2e37e4028ac..e717fd5d9e291 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -537,6 +537,12 @@ void curl_multi_free_obj(zend_object *object) php_curl *ch; zval *pz_ch; + if (!mh->multi) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&mh->std); + return; + } + for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { if (!(OBJ_FLAGS(Z_OBJ_P(pz_ch)) & IS_OBJ_FREE_CALLED)) { diff --git a/ext/curl/tests/bug80121.phpt b/ext/curl/tests/bug80121.phpt new file mode 100644 index 0000000000000..9239cf007fb0a --- /dev/null +++ b/ext/curl/tests/bug80121.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #80121: Null pointer deref if CurlHandle directly instantiated +--FILE-- +getMessage(), "\n"; +} +try { + new CurlMultiHandle; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + new CurlShareHandle; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot directly construct CurlHandle, use curl_init() instead +Cannot directly construct CurlMultiHandle, use curl_multi_init() instead +Cannot directly construct CurlShareHandle, use curl_share_init() instead From 62c6d6952ead055b2a08636eacdce6bb74168de1 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Oct 2020 17:10:56 +0200 Subject: [PATCH 08/31] Add test instantiating all objects Intended to find issues in opaque object destructors. Closes GH-6251. --- Zend/tests/instantiate_all_classes.phpt | 15 +++++++++++++++ ext/gd/gd.c | 6 +++--- ext/openssl/openssl.c | 5 +---- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/instantiate_all_classes.phpt diff --git a/Zend/tests/instantiate_all_classes.phpt b/Zend/tests/instantiate_all_classes.phpt new file mode 100644 index 0000000000000..b8d82530f320a --- /dev/null +++ b/Zend/tests/instantiate_all_classes.phpt @@ -0,0 +1,15 @@ +--TEST-- +Try to instantiate all classes without arguments +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 6f1ab3cf42b11..462b1259689b5 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -199,9 +199,9 @@ zend_object *php_gd_image_object_create(zend_class_entry *class_type) static void php_gd_image_object_free(zend_object *intern) { php_gd_image_object *img_obj_ptr = php_gd_exgdimage_from_zobj_p(intern); - gdImageDestroy(img_obj_ptr->image); - img_obj_ptr->image = NULL; - + if (img_obj_ptr->image) { + gdImageDestroy(img_obj_ptr->image); + } zend_object_std_dtor(intern); } diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 161396f4941e2..abaf88f15a38c 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -233,10 +233,7 @@ static void php_openssl_pkey_free_obj(zend_object *object) { php_openssl_pkey_object *key_object = php_openssl_pkey_from_obj(object); - EVP_PKEY *pkey = key_object->pkey; - assert(pkey != NULL); - EVP_PKEY_free(pkey); - + EVP_PKEY_free(key_object->pkey); zend_object_std_dtor(&key_object->std); } From 29dd1240f3b9a199e19f1c2e4b47cc6f44461e87 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 1 Oct 2020 22:39:58 +0300 Subject: [PATCH 09/31] Clenup BINARY_OP + SEND_VAL optimization --- ext/opcache/jit/zend_jit.c | 26 +++++------ ext/opcache/jit/zend_jit_trace.c | 19 ++++++--- ext/opcache/jit/zend_jit_x86.dasc | 71 ++++++++++--------------------- 3 files changed, 51 insertions(+), 65 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 111b5f47e9075..91f1a5d458bdc 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2034,7 +2034,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op zend_uchar smart_branch_opcode; uint32_t target_label, target_label2; uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info; - zend_bool send_result; zend_jit_addr op1_addr, op1_def_addr, op2_addr, op2_def_addr, res_addr; zend_class_entry *ce; zend_bool ce_is_instanceof; @@ -2306,11 +2305,12 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { i++; - send_result = 1; res_use_info = -1; - res_addr = 0; /* set inside backend */ + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { - send_result = 0; res_use_info = RES_USE_INFO(); res_addr = RES_REG_ADDR(); } @@ -2318,7 +2318,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op op1_info, OP1_RANGE(), OP1_REG_ADDR(), op2_info, OP2_RANGE(), OP2_REG_ADDR(), res_use_info, RES_INFO(), res_addr, - send_result, zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } @@ -2353,11 +2352,12 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { i++; - send_result = 1; res_use_info = -1; - res_addr = 0; /* set inside backend */ + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { - send_result = 0; res_use_info = RES_USE_INFO(); res_addr = RES_REG_ADDR(); } @@ -2366,7 +2366,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op op1_info, OP1_REG_ADDR(), op2_info, OP2_REG_ADDR(), res_use_info, res_info, res_addr, - send_result, (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa), zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; @@ -2392,12 +2391,15 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { i++; - send_result = 1; + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { - send_result = 0; + res_addr = RES_REG_ADDR(); } if (!zend_jit_concat(&dasm_state, opline, - op1_info, op2_info, send_result, + op1_info, op2_info, res_addr, zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index caf162e44d480..27ff183ba487e 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3524,7 +3524,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } send_result = 1; res_use_info = -1; - res_addr = 0; /* set inside backend */ + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { send_result = 0; if (opline->result_type == IS_CV) { @@ -3543,7 +3546,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_info, OP1_RANGE(), OP1_REG_ADDR(), op2_info, OP2_RANGE(), OP2_REG_ADDR(), res_use_info, res_info, res_addr, - send_result, zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } @@ -3595,7 +3597,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } send_result = 1; res_use_info = -1; - res_addr = 0; /* set inside backend */ + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { send_result = 0; if (opline->result_type == IS_CV) { @@ -3614,7 +3619,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_info, OP1_REG_ADDR(), op2_info, OP2_REG_ADDR(), res_use_info, res_info, res_addr, - send_result, (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa), zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; @@ -3659,11 +3663,16 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par p++; } send_result = 1; + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } } else { send_result = 0; + res_addr = RES_REG_ADDR(); } if (!zend_jit_concat(&dasm_state, opline, - op1_info, op2_info, send_result, + op1_info, op2_info, res_addr, zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index fd04435818516..09143b21197fd 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -1656,6 +1656,16 @@ static void zend_jit_start_reuse_ip(void) reuse_ip = 1; } +static int zend_jit_reuse_ip(dasm_State **Dst) +{ + if (!reuse_ip) { + zend_jit_start_reuse_ip(); + | // call = EX(call); + | mov RX, EX->call + } + return 1; +} + static void zend_jit_stop_reuse_ip(void) { reuse_ip = 0; @@ -4709,21 +4719,12 @@ static int zend_jit_math_helper(dasm_State **Dst, return 1; } -static int zend_jit_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info, zend_jit_addr res_addr, zend_bool send_result, int may_overflow, int may_throw) +static int zend_jit_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info, zend_jit_addr res_addr, int may_overflow, int may_throw) { ZEND_ASSERT(!(op1_info & MAY_BE_UNDEF) && !(op2_info & MAY_BE_UNDEF)); ZEND_ASSERT((op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) && (op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))); - if (send_result) { - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call - } - res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); - } - if (!zend_jit_math_helper(Dst, opline, opline->opcode, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, opline->result.var, res_addr, res_info, res_use_info, may_overflow, may_throw)) { return 0; } @@ -5049,20 +5050,11 @@ static int zend_jit_long_math_helper(dasm_State **Dst, return 1; } -static int zend_jit_long_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_ssa_range *op1_range, zend_jit_addr op1_addr, uint32_t op2_info, zend_ssa_range *op2_range, zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info, zend_jit_addr res_addr, zend_bool send_result, int may_throw) +static int zend_jit_long_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_ssa_range *op1_range, zend_jit_addr op1_addr, uint32_t op2_info, zend_ssa_range *op2_range, zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info, zend_jit_addr res_addr, int may_throw) { ZEND_ASSERT(!(op1_info & MAY_BE_UNDEF) && !(op2_info & MAY_BE_UNDEF)); ZEND_ASSERT((op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG)); - if (send_result) { - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call - } - res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); - } - if (!zend_jit_long_math_helper(Dst, opline, opline->opcode, opline->op1_type, opline->op1, op1_addr, op1_info, op1_range, opline->op2_type, opline->op2, op2_addr, op2_info, op2_range, @@ -5160,9 +5152,9 @@ static int zend_jit_concat_helper(dasm_State **Dst, return 1; } -static int zend_jit_concat(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info, zend_bool send_result, int may_throw) +static int zend_jit_concat(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info, zend_jit_addr res_addr, int may_throw) { - zend_jit_addr op1_addr, op2_addr, res_addr; + zend_jit_addr op1_addr, op2_addr; ZEND_ASSERT(!(op1_info & MAY_BE_UNDEF) && !(op2_info & MAY_BE_UNDEF)); ZEND_ASSERT((op1_info & MAY_BE_STRING) && (op2_info & MAY_BE_STRING)); @@ -5170,16 +5162,6 @@ static int zend_jit_concat(dasm_State **Dst, const zend_op *opline, uint32_t op1 op1_addr = OP1_ADDR(); op2_addr = OP2_ADDR(); - if (send_result) { - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call - } - res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); - } else { - res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); - } return zend_jit_concat_helper(Dst, opline, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, res_addr, may_throw); } @@ -10011,10 +9993,8 @@ static int zend_jit_send_val(dasm_State **Dst, const zend_op *opline, uint32_t o ZEND_ASSERT(opline->opcode == ZEND_SEND_VAL || arg_num <= MAX_ARG_FLAG_NUM); - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call + if (!zend_jit_reuse_ip(Dst)) { + return 0; } if (opline->opcode == ZEND_SEND_VAL_EX) { @@ -10093,10 +10073,8 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend op1_addr = OP1_ADDR(); arg_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, opline->result.var); - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call + if (!zend_jit_reuse_ip(Dst)) { + return 0; } if (opline->op1_type == IS_VAR) { @@ -10180,10 +10158,8 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend arg_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, opline->result.var); - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call + if (!zend_jit_reuse_ip(Dst)) { + return 0; } if (opline->opcode == ZEND_SEND_VAR_EX) { @@ -10427,11 +10403,10 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline) // if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { uint32_t mask = (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF) << ((arg_num + 3) * 2); - if (!reuse_ip) { - zend_jit_start_reuse_ip(); - | // call = EX(call); - | mov RX, EX->call + if (!zend_jit_reuse_ip(Dst)) { + return 0; } + | mov r0, EX:RX->func | test dword [r0 + offsetof(zend_function, quick_arg_flags)], mask | jnz >1 From ceef8ad4904a26af8221ddadc174618287b62a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 09:53:57 +0200 Subject: [PATCH 10/31] Review parameter names in ext/sysvmsg Closes GH-6247 --- ext/sysvmsg/sysvmsg.stub.php | 21 +++++++++++++++------ ext/sysvmsg/sysvmsg_arginfo.h | 16 ++++++++-------- ext/sysvmsg/tests/005.phpt | 4 ++-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ext/sysvmsg/sysvmsg.stub.php b/ext/sysvmsg/sysvmsg.stub.php index cb5174027b3b0..2a0c9cdc95436 100644 --- a/ext/sysvmsg/sysvmsg.stub.php +++ b/ext/sysvmsg/sysvmsg.stub.php @@ -6,19 +6,28 @@ final class SysvMessageQueue { } -function msg_get_queue(int $key, int $perms = 0666): SysvMessageQueue|false {} +function msg_get_queue(int $key, int $permissions = 0666): SysvMessageQueue|false {} /** * @param string|int|float|bool $message - * @param int $errorcode + * @param int $error_code */ -function msg_send(SysvMessageQueue $queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, &$errorcode = null): bool {} +function msg_send(SysvMessageQueue $queue, int $message_type, $message, bool $serialize = true, bool $blocking = true, &$error_code = null): bool {} /** - * @param int $msgtype - * @param int $errorcode + * @param int $received_message_type + * @param int $error_code */ -function msg_receive(SysvMessageQueue $queue, int $desiredmsgtype, &$msgtype, int $maxsize, mixed &$message, bool $unserialize = true, int $flags = 0, &$errorcode = null): bool {} +function msg_receive( + SysvMessageQueue $queue, + int $desired_message_type, + &$received_message_type, + int $max_message_size, + mixed &$message, + bool $unserialize = true, + int $flags = 0, + &$error_code = null +): bool {} function msg_remove_queue(SysvMessageQueue $queue): bool {} diff --git a/ext/sysvmsg/sysvmsg_arginfo.h b/ext/sysvmsg/sysvmsg_arginfo.h index 2eadbed14420e..804f1768b300d 100644 --- a/ext/sysvmsg/sysvmsg_arginfo.h +++ b/ext/sysvmsg/sysvmsg_arginfo.h @@ -1,29 +1,29 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 40f03edb33ac213c9f436d5e7ea85ec2750fdf6e */ + * Stub hash: 3f918caddccfebee1f1048abd4a23672724436ad */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_msg_get_queue, 0, 1, SysvMessageQueue, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perms, IS_LONG, 0, "0666") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permissions, IS_LONG, 0, "0666") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_send, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) - ZEND_ARG_TYPE_INFO(0, msgtype, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, message_type, IS_LONG, 0) ZEND_ARG_INFO(0, message) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, serialize, _IS_BOOL, 0, "true") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, blocking, _IS_BOOL, 0, "true") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, errorcode, "null") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, error_code, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_receive, 0, 5, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) - ZEND_ARG_TYPE_INFO(0, desiredmsgtype, IS_LONG, 0) - ZEND_ARG_INFO(1, msgtype) - ZEND_ARG_TYPE_INFO(0, maxsize, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, desired_message_type, IS_LONG, 0) + ZEND_ARG_INFO(1, received_message_type) + ZEND_ARG_TYPE_INFO(0, max_message_size, IS_LONG, 0) ZEND_ARG_TYPE_INFO(1, message, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, unserialize, _IS_BOOL, 0, "true") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, errorcode, "null") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, error_code, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_remove_queue, 0, 1, _IS_BOOL, 0) diff --git a/ext/sysvmsg/tests/005.phpt b/ext/sysvmsg/tests/005.phpt index 51713e2fab186..ac3592a528b82 100644 --- a/ext/sysvmsg/tests/005.phpt +++ b/ext/sysvmsg/tests/005.phpt @@ -46,7 +46,7 @@ bool(false) bool(false) bool(false) bool(true) -msg_receive(): Argument #4 ($maxsize) must be greater than 0 +msg_receive(): Argument #4 ($max_message_size) must be greater than 0 Warning: msg_send(): msgsnd failed: Invalid argument in %s on line %d bool(false) @@ -56,7 +56,7 @@ bool(false) bool(false) bool(false) bool(true) -msg_receive(): Argument #4 ($maxsize) must be greater than 0 +msg_receive(): Argument #4 ($max_message_size) must be greater than 0 Warning: msg_send(): msgsnd failed: Invalid argument in %s on line %d bool(false) From 85949d749bcbe63b2ef2e905e67735e84f235fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 10:00:43 +0200 Subject: [PATCH 11/31] Review parameter names in ext/sysvsem Closes GH-6248 --- ext/sysvsem/sysvsem.stub.php | 4 ++-- ext/sysvsem/sysvsem_arginfo.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/sysvsem/sysvsem.stub.php b/ext/sysvsem/sysvsem.stub.php index 3265984e70f9c..8da71b09fb781 100644 --- a/ext/sysvsem/sysvsem.stub.php +++ b/ext/sysvsem/sysvsem.stub.php @@ -6,9 +6,9 @@ final class SysvSemaphore { } -function sem_get(int $key, int $max_acquire = 1, int $perm = 0666, bool $auto_release = true): SysvSemaphore|false {} +function sem_get(int $key, int $max_acquire = 1, int $permissions = 0666, bool $auto_release = true): SysvSemaphore|false {} -function sem_acquire(SysvSemaphore $semaphore, bool $nowait = false): bool {} +function sem_acquire(SysvSemaphore $semaphore, bool $non_blocking = false): bool {} function sem_release(SysvSemaphore $semaphore): bool {} diff --git a/ext/sysvsem/sysvsem_arginfo.h b/ext/sysvsem/sysvsem_arginfo.h index 07ebe6bf545e0..8d6f0ac4094f5 100644 --- a/ext/sysvsem/sysvsem_arginfo.h +++ b/ext/sysvsem/sysvsem_arginfo.h @@ -1,16 +1,16 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d00524488977b77475f9aa78c132a6dd53ab4dd0 */ + * Stub hash: 745e7cf135c7d1c9ad09d1ea1ab6cf2a8181433a */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_sem_get, 0, 1, SysvSemaphore, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, max_acquire, IS_LONG, 0, "1") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perm, IS_LONG, 0, "0666") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permissions, IS_LONG, 0, "0666") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, auto_release, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sem_acquire, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, semaphore, SysvSemaphore, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nowait, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, non_blocking, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sem_release, 0, 1, _IS_BOOL, 0) From 4a30c7684587fcb34c50f796b23518705e5e5874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 10:09:27 +0200 Subject: [PATCH 12/31] Review parameter names in ext/sysvshm Closes GH-6249 --- ext/sysvshm/sysvshm.stub.php | 10 +++++----- ext/sysvshm/sysvshm_arginfo.h | 14 +++++++------- ext/sysvshm/tests/002.phpt | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ext/sysvshm/sysvshm.stub.php b/ext/sysvshm/sysvshm.stub.php index f775032f46dce..4f2799a349ec0 100644 --- a/ext/sysvshm/sysvshm.stub.php +++ b/ext/sysvshm/sysvshm.stub.php @@ -6,16 +6,16 @@ final class SysvSharedMemory { } -function shm_attach(int $key, ?int $memsize = null, int $perm = 0666): SysvSharedMemory|false {} +function shm_attach(int $key, ?int $size = null, int $permissions = 0666): SysvSharedMemory|false {} function shm_detach(SysvSharedMemory $shm): bool {} -function shm_has_var(SysvSharedMemory $shm, int $variable_key): bool {} +function shm_has_var(SysvSharedMemory $shm, int $key): bool {} function shm_remove(SysvSharedMemory $shm): bool {} -function shm_put_var(SysvSharedMemory $shm, int $variable_key, mixed $variable): bool {} +function shm_put_var(SysvSharedMemory $shm, int $key, mixed $value): bool {} -function shm_get_var(SysvSharedMemory $shm, int $variable_key): mixed {} +function shm_get_var(SysvSharedMemory $shm, int $key): mixed {} -function shm_remove_var(SysvSharedMemory $shm, int $variable_key): bool {} +function shm_remove_var(SysvSharedMemory $shm, int $key): bool {} diff --git a/ext/sysvshm/sysvshm_arginfo.h b/ext/sysvshm/sysvshm_arginfo.h index 4e0078038cc3f..d6f09d1426561 100644 --- a/ext/sysvshm/sysvshm_arginfo.h +++ b/ext/sysvshm/sysvshm_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 9a57af33a6658387f706ea121612c0f0eb55e5b3 */ + * Stub hash: 12f78387e5b7c436b608dbecc4c6b3eec82b6db1 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_shm_attach, 0, 1, SysvSharedMemory, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, memsize, IS_LONG, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perm, IS_LONG, 0, "0666") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, size, IS_LONG, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permissions, IS_LONG, 0, "0666") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_detach, 0, 1, _IS_BOOL, 0) @@ -13,20 +13,20 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_has_var, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) - ZEND_ARG_TYPE_INFO(0, variable_key, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_END_ARG_INFO() #define arginfo_shm_remove arginfo_shm_detach ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_put_var, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) - ZEND_ARG_TYPE_INFO(0, variable_key, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, variable, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_get_var, 0, 2, IS_MIXED, 0) ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) - ZEND_ARG_TYPE_INFO(0, variable_key, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_END_ARG_INFO() #define arginfo_shm_remove_var arginfo_shm_has_var diff --git a/ext/sysvshm/tests/002.phpt b/ext/sysvshm/tests/002.phpt index aeec6f6e1b454..981bbf3230d77 100644 --- a/ext/sysvshm/tests/002.phpt +++ b/ext/sysvshm/tests/002.phpt @@ -55,11 +55,11 @@ shm_remove($s); echo "Done\n"; ?> --EXPECTF-- -shm_attach(): Argument #2 ($memsize) must be greater than 0 -shm_attach(): Argument #2 ($memsize) must be greater than 0 -shm_attach(): Argument #2 ($memsize) must be greater than 0 -shm_attach(): Argument #2 ($memsize) must be greater than 0 -shm_attach(): Argument #2 ($memsize) must be greater than 0 +shm_attach(): Argument #2 ($size) must be greater than 0 +shm_attach(): Argument #2 ($size) must be greater than 0 +shm_attach(): Argument #2 ($size) must be greater than 0 +shm_attach(): Argument #2 ($size) must be greater than 0 +shm_attach(): Argument #2 ($size) must be greater than 0 object(SysvSharedMemory)#%d (0) { } object(SysvSharedMemory)#%d (0) { From 1666cfcca0356168e2b61610b98052c3b85cae9d Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Fri, 2 Oct 2020 09:32:52 +0200 Subject: [PATCH 13/31] [ci skip] moved soap fix to 7.3.23 When committing I didn't notice that version had been just bumped --- NEWS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 214c5ac342e63..d3bc469cd46a2 100644 --- a/NEWS +++ b/NEWS @@ -60,7 +60,11 @@ PHP NEWS - PDO: . Fixed bug #80027 (Terrible performance using $query->fetch on queries with - many bind parameters (Matteo) + many bind parameters). (Matteo) + +- SOAP: + . Fixed bug #47021 (SoapClient stumbles over WSDL delivered with + "Transfer-Encoding: chunked"). (Matteo) - Standard: . Fixed bug #79986 (str_ireplace bug with diacritics characters). (cmb) @@ -104,10 +108,6 @@ PHP NEWS . Fixed bug #64705 (errorInfo property of PDOException is null when PDO::__construct() fails). (Ahmed Abdou) -- SOAP: - . Fixed bug #47021 (SoapClient stumbles over WSDL delivered with - "Transfer-Encoding: chunked"). (Matteo) - - Standard: . Fixed bug #79930 (array_merge_recursive() crashes when called with array with single reference). (Nikita) From 7c48479f62c614198fc4219d74a1c385c2789850 Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Fri, 2 Oct 2020 09:33:50 +0200 Subject: [PATCH 14/31] [ci skip] moved soap fix to 7.4.11 When committing I didn't notice that version had been just bumped --- NEWS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index d47582e51b945..826c0f0a7142a 100644 --- a/NEWS +++ b/NEWS @@ -71,7 +71,11 @@ PHP NEWS - PDO: . Fixed bug #80027 (Terrible performance using $query->fetch on queries with - many bind parameters (Matteo) + many bind parameters). (Matteo) + +- SOAP: + . Fixed bug #47021 (SoapClient stumbles over WSDL delivered with + "Transfer-Encoding: chunked"). (Matteo) - Standard: . Fixed bug #79986 (str_ireplace bug with diacritics characters). (cmb) @@ -123,10 +127,6 @@ PHP NEWS . Fixed bug #79724 (Return type does not match in ext/session/mod_mm.c). (Nikita) -- SOAP: - . Fixed bug #47021 (SoapClient stumbles over WSDL delivered with - "Transfer-Encoding: chunked"). (Matteo) - - Standard: . Fixed bug #79930 (array_merge_recursive() crashes when called with array with single reference). (Nikita) From d7243ce2912375bbdccda318f754a45825d6195c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 09:39:15 +0200 Subject: [PATCH 15/31] Add UPGRADING note for substr() behavior [ci skip] --- UPGRADING | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING b/UPGRADING index 05c8eef1e9ec9..0c15b1ecbe990 100644 --- a/UPGRADING +++ b/UPGRADING @@ -608,6 +608,9 @@ PHP 8.0 UPGRADE NOTES . Calling crypt() without an explicit salt is no longer supported. If you would like to produce a strong hash with an auto-generated salt, use password_hash() instead. + . substr(), mb_substr(), iconv_substr() and grapheme_substr() now consistently + clamp out-of-bounds offsets to the string boundary. Previously, false was + returned instead of the empty string in some cases. - Sysvmsg: . msg_get_queue() will now return an SysvMessageQueue object rather than a From fbf153a21015e93921ddfcda62a51ee7cf860c41 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 2 Oct 2020 10:48:45 +0300 Subject: [PATCH 16/31] Fixed possible incorrect register usage --- ext/opcache/jit/zend_jit_x86.dasc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 09143b21197fd..eab4293a7d61d 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4797,7 +4797,12 @@ static int zend_jit_long_math_helper(dasm_State **Dst, if (opcode == ZEND_MOD) { result_reg = ZREG_RAX; } else if (Z_MODE(res_addr) == IS_REG) { - result_reg = Z_REG(res_addr); + if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) + && opline->op2_type != IS_CONST) { + result_reg = ZREG_R0; + } else { + result_reg = Z_REG(res_addr); + } } else if (Z_MODE(op1_addr) == IS_REG && Z_LAST_USE(op1_addr)) { result_reg = Z_REG(op1_addr); } else if (Z_REG(res_addr) != ZREG_R0) { From b0e77066bd5b692534afde7aafcea877c91ea13b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 2 Oct 2020 11:01:35 +0300 Subject: [PATCH 17/31] Fixed JIT for BINARY_OP with expected overflow --- ext/opcache/jit/zend_jit_x86.dasc | 35 ++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index eab4293a7d61d..532bdb97f8158 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4185,7 +4185,7 @@ static int zend_jit_math_long_long(dasm_State **Dst, zend_bool same_ops = zend_jit_same_addr(op1_addr, op2_addr); zend_reg result_reg; - if (Z_MODE(res_addr) == IS_REG) { + if (Z_MODE(res_addr) == IS_REG && (res_info & MAY_BE_LONG)) { result_reg = Z_REG(res_addr); } else if (Z_MODE(op1_addr) == IS_REG && Z_LAST_USE(op1_addr)) { result_reg = Z_REG(op1_addr); @@ -4255,13 +4255,23 @@ static int zend_jit_math_long_long(dasm_State **Dst, if (res_info & MAY_BE_GUARD) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); - | jo &exit_addr + if ((res_info & MAY_BE_ANY) == MAY_BE_LONG) { + | jo &exit_addr + } else if ((res_info & MAY_BE_ANY) == MAY_BE_DOUBLE) { + | jno &exit_addr + } else { + ZEND_UNREACHABLE(); + } } else { - | jo >1 + if (res_info & MAY_BE_LONG) { + | jo >1 + } else { + | jno >1 + } } } - if (Z_MODE(res_addr) == IS_MEM_ZVAL) { + if (Z_MODE(res_addr) == IS_MEM_ZVAL && (res_info & MAY_BE_LONG)) { | SET_ZVAL_LVAL res_addr, Ra(result_reg) if (Z_MODE(op1_addr) != IS_MEM_ZVAL || Z_REG(op1_addr) != Z_REG(res_addr) || Z_OFFSET(op1_addr) != Z_OFFSET(res_addr)) { if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_GUARD)) != MAY_BE_LONG) { @@ -4270,12 +4280,14 @@ static int zend_jit_math_long_long(dasm_State **Dst, } } - if (may_overflow && !(res_info & MAY_BE_GUARD)) { + if (may_overflow && (!(res_info & MAY_BE_GUARD) || (res_info & MAY_BE_ANY) == MAY_BE_DOUBLE)) { zend_reg tmp_reg1 = ZREG_XMM0; zend_reg tmp_reg2 = ZREG_XMM1; - |.cold_code - |1: + if (res_info & MAY_BE_LONG) { + |.cold_code + |1: + } do { if ((Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op1_addr)) == 1) || @@ -4311,11 +4323,14 @@ static int zend_jit_math_long_long(dasm_State **Dst, | SSE_SET_ZVAL_DVAL res_addr, tmp_reg1 } while (0); - if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_GUARD)) != MAY_BE_DOUBLE) { + if (Z_MODE(res_addr) == IS_MEM_ZVAL + && (res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_GUARD)) != MAY_BE_DOUBLE) { | SET_ZVAL_TYPE_INFO res_addr, IS_DOUBLE } - | jmp >2 - |.code + if (res_info & MAY_BE_LONG) { + | jmp >2 + |.code + } |2: } From 109fb3e57de34cbbd948d582474e83c4cbe35a96 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 2 Oct 2020 12:06:02 +0300 Subject: [PATCH 18/31] Copy optimization for (BINARY_OP/ACCIGN + SEND_VAL) --- ext/opcache/jit/zend_jit.c | 72 ++++++++++------- ext/opcache/jit/zend_jit_trace.c | 125 +++++++++++++++++++++--------- ext/opcache/jit/zend_jit_x86.dasc | 3 +- 3 files changed, 135 insertions(+), 65 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 91f1a5d458bdc..7c9a8bb7cff2e 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2299,7 +2299,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op || !(op2_info & MAY_BE_LONG)) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (i + 1) <= end && (opline+1)->opcode == ZEND_SEND_VAL && (opline+1)->op1_type == IS_TMP_VAR @@ -2312,7 +2314,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } else { res_use_info = RES_USE_INFO(); - res_addr = RES_REG_ADDR(); } if (!zend_jit_long_math(&dasm_state, opline, op1_info, OP1_RANGE(), OP1_REG_ADDR(), @@ -2337,16 +2338,14 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (opline->opcode == ZEND_ADD && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { - if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) { - goto jit_failure; - } - goto done; - } - if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || + /* pass */ + } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (i + 1) <= end && (opline+1)->opcode == ZEND_SEND_VAL && (opline+1)->op1_type == IS_TMP_VAR @@ -2359,16 +2358,23 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } else { res_use_info = RES_USE_INFO(); - res_addr = RES_REG_ADDR(); } res_info = RES_INFO(); - if (!zend_jit_math(&dasm_state, opline, - op1_info, OP1_REG_ADDR(), - op2_info, OP2_REG_ADDR(), - res_use_info, res_info, res_addr, - (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa), - zend_may_throw(opline, ssa_op, op_array, ssa))) { - goto jit_failure; + if (opline->opcode == ZEND_ADD && + (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && + (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { + if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) { + goto jit_failure; + } + } else { + if (!zend_jit_math(&dasm_state, opline, + op1_info, OP1_REG_ADDR(), + op2_info, OP2_REG_ADDR(), + res_use_info, res_info, res_addr, + (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa), + zend_may_throw(opline, ssa_op, op_array, ssa))) { + goto jit_failure; + } } goto done; case ZEND_CONCAT: @@ -2385,7 +2391,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op !(op2_info & MAY_BE_STRING)) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (i + 1) <= end && (opline+1)->opcode == ZEND_SEND_VAL && (opline+1)->op1_type == IS_TMP_VAR @@ -2395,8 +2403,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (!zend_jit_reuse_ip(&dasm_state)) { goto jit_failure; } - } else { - res_addr = RES_REG_ADDR(); } if (!zend_jit_concat(&dasm_state, opline, op1_info, op2_info, res_addr, @@ -2624,13 +2630,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) { break; } - if (opline->result_type == IS_UNUSED) { - res_addr = 0; - res_info = -1; - } else { - res_addr = RES_REG_ADDR(); - res_info = RES_INFO(); - } op2_addr = OP2_REG_ADDR(); if (ra && ssa->ops[opline - op_array->opcodes].op2_def >= 0 @@ -2639,6 +2638,25 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } else { op2_def_addr = op2_addr; } + if (opline->result_type == IS_UNUSED) { + res_addr = 0; + res_info = -1; + } else { + res_addr = RES_REG_ADDR(); + res_info = RES_INFO(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR + && (i + 1) <= end + && (opline+1)->opcode == ZEND_SEND_VAL + && (opline+1)->op1_type == IS_TMP_VAR + && (opline+1)->op1.var == opline->result.var) { + i++; + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } + } + } if (!zend_jit_assign(&dasm_state, opline, OP1_INFO(), OP1_REG_ADDR(), OP1_DEF_INFO(), OP1_DEF_REG_ADDR(), diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 27ff183ba487e..0d691f8c2da8f 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3502,10 +3502,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par || !(op2_info & MAY_BE_LONG)) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (p+1)->op == ZEND_JIT_TRACE_VM && (p+1)->opline == opline + 1 - && (opline+1)->opcode == ZEND_SEND_VAL + && ((opline+1)->opcode == ZEND_SEND_VAL + || ((opline+1)->opcode == ZEND_SEND_VAL_EX + && frame + && frame->call + && frame->call->func + && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num))) && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { p++; @@ -3529,7 +3536,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } } else { - send_result = 0; if (opline->result_type == IS_CV) { res_use_info = RES_USE_INFO(); } else { @@ -3539,7 +3545,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par res_use_info = -1; #endif } - res_addr = RES_REG_ADDR(); } res_info = RES_INFO(); if (!zend_jit_long_math(&dasm_state, opline, @@ -3564,19 +3569,22 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (opline->opcode == ZEND_ADD && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { - if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) { - goto jit_failure; - } - goto done; - } - if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || + /* pass */ + } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (p+1)->op == ZEND_JIT_TRACE_VM && (p+1)->opline == opline + 1 - && (opline+1)->opcode == ZEND_SEND_VAL + && ((opline+1)->opcode == ZEND_SEND_VAL + || ((opline+1)->opcode == ZEND_SEND_VAL_EX + && frame + && frame->call + && frame->call->func + && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num))) && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { p++; @@ -3602,7 +3610,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } } else { - send_result = 0; if (opline->result_type == IS_CV) { res_use_info = RES_USE_INFO(); } else { @@ -3612,19 +3619,27 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par res_use_info = -1; #endif } - res_addr = RES_REG_ADDR(); } res_info = RES_INFO(); - if (!zend_jit_math(&dasm_state, opline, - op1_info, OP1_REG_ADDR(), - op2_info, OP2_REG_ADDR(), - res_use_info, res_info, res_addr, - (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa), - zend_may_throw(opline, ssa_op, op_array, ssa))) { - goto jit_failure; - } - if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)) { - ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD; + if (opline->opcode == ZEND_ADD && + (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && + (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { + if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) { + goto jit_failure; + } + } else { + if (!zend_jit_math(&dasm_state, opline, + op1_info, OP1_REG_ADDR(), + op2_info, OP2_REG_ADDR(), + res_use_info, res_info, res_addr, + (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa), + zend_may_throw(opline, ssa_op, op_array, ssa))) { + goto jit_failure; + } + if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD) + || (res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_DOUBLE|MAY_BE_GUARD)) { + ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD; + } } goto done; case ZEND_CONCAT: @@ -3640,10 +3655,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par !(op2_info & MAY_BE_STRING)) { break; } - if (opline->result_type == IS_TMP_VAR + res_addr = RES_REG_ADDR(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR && (p+1)->op == ZEND_JIT_TRACE_VM && (p+1)->opline == opline + 1 - && (opline+1)->opcode == ZEND_SEND_VAL + && ((opline+1)->opcode == ZEND_SEND_VAL + || ((opline+1)->opcode == ZEND_SEND_VAL_EX + && frame + && frame->call + && frame->call->func + && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num))) && (opline+1)->op1_type == IS_TMP_VAR && (opline+1)->op1.var == opline->result.var) { p++; @@ -3667,9 +3689,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (!zend_jit_reuse_ip(&dasm_state)) { goto jit_failure; } - } else { - send_result = 0; - res_addr = RES_REG_ADDR(); } if (!zend_jit_concat(&dasm_state, opline, op1_info, op2_info, res_addr, @@ -4028,13 +4047,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (opline->op1_type != IS_CV) { break; } - if (opline->result_type == IS_UNUSED) { - res_addr = 0; - res_info = -1; - } else { - res_addr = RES_REG_ADDR(); - res_info = RES_INFO(); - } op2_addr = OP2_REG_ADDR(); if (ra && ssa_op->op2_def >= 0 @@ -4072,6 +4084,47 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_def_info &= ~MAY_BE_REF; } } + if (opline->result_type == IS_UNUSED) { + res_addr = 0; + res_info = -1; + } else { + res_addr = RES_REG_ADDR(); + res_info = RES_INFO(); + if (Z_MODE(res_addr) != IS_REG + && opline->result_type == IS_TMP_VAR + && (p+1)->op == ZEND_JIT_TRACE_VM + && (p+1)->opline == opline + 1 + && ((opline+1)->opcode == ZEND_SEND_VAL + || ((opline+1)->opcode == ZEND_SEND_VAL_EX + && frame + && frame->call + && frame->call->func + && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num))) + && (opline+1)->op1_type == IS_TMP_VAR + && (opline+1)->op1.var == opline->result.var) { + p++; + if (frame->call + && frame->call->func + && frame->call->func->type == ZEND_USER_FUNCTION) { + uint8_t res_type = p->op1_type; + if (res_type & IS_TRACE_REFERENCE) { + res_type = IS_UNKNOWN; + } + if (res_type != IS_UNKNOWN) { + zend_jit_trace_send_type(opline+1, frame->call, res_type); + } + } + while ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE || + (p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) { + p++; + } + send_result = 1; + res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var); + if (!zend_jit_reuse_ip(&dasm_state)) { + goto jit_failure; + } + } + } if (!zend_jit_assign(&dasm_state, opline, op1_info, op1_addr, op1_def_info, op1_def_addr, diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 532bdb97f8158..5e097e27e73c6 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4749,11 +4749,10 @@ static int zend_jit_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_i return 1; } -static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info) +static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info, zend_jit_addr res_addr) { zend_jit_addr op1_addr = OP1_ADDR(); zend_jit_addr op2_addr = OP2_ADDR(); - zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); | GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr From 6b00196e04d29479412e1de6dabc5b8a62709686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Fri, 2 Oct 2020 00:20:45 +0200 Subject: [PATCH 19/31] Review parameter names in ext/pcre Closes GH-6259 --- ext/pcre/php_pcre.c | 2 +- ext/pcre/php_pcre.stub.php | 18 +++++++++--------- ext/pcre/php_pcre_arginfo.h | 18 +++++++++--------- ext/pcre/tests/bug21732.phpt | 2 +- ext/pcre/tests/preg_grep_error1.phpt | 4 ++-- ext/pcre/tests/preg_match_all_error3.phpt | 2 +- ext/pcre/tests/preg_replace_error1.phpt | 2 +- ext/pcre/tests/preg_replace_error2.phpt | 4 ++-- ext/standard/tests/streams/bug61115.phpt | 2 +- sapi/cli/tests/006.phpt | 20 ++++++++++---------- 10 files changed, 37 insertions(+), 37 deletions(-) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 42c423e6bd8cf..ee340829ee611 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -2295,7 +2295,7 @@ static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool is_filter) /* If replace is an array then the regex argument needs to also be an array */ if (replace_ht && !regex_ht) { - zend_argument_type_error(1, "must be of type array when argument #2 ($replace) is an array, string given"); + zend_argument_type_error(1, "must be of type array when argument #2 ($replacement) is an array, string given"); RETURN_THROWS(); } diff --git a/ext/pcre/php_pcre.stub.php b/ext/pcre/php_pcre.stub.php index f620d119fd538..b2862a2f62ee1 100644 --- a/ext/pcre/php_pcre.stub.php +++ b/ext/pcre/php_pcre.stub.php @@ -2,29 +2,29 @@ /** @generate-function-entries */ -/** @param array $subpatterns */ -function preg_match(string $pattern, string $subject, &$subpatterns = null, int $flags = 0, int $offset = 0): int|false {} +/** @param array $matches */ +function preg_match(string $pattern, string $subject, &$matches = null, int $flags = 0, int $offset = 0): int|false {} -/** @param array $subpatterns */ -function preg_match_all(string $pattern, string $subject, &$subpatterns = null, int $flags = 0, int $offset = 0): int|false|null {} +/** @param array $matches */ +function preg_match_all(string $pattern, string $subject, &$matches = null, int $flags = 0, int $offset = 0): int|false|null {} /** @param int $count */ -function preg_replace(string|array $regex, string|array $replace, string|array $subject, int $limit = -1, &$count = null): string|array|null {} +function preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, &$count = null): string|array|null {} /** @param int $count */ -function preg_filter(string|array $regex, string|array $replace, string|array $subject, int $limit = -1, &$count = null): string|array|null {} +function preg_filter(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, &$count = null): string|array|null {} /** @param int $count */ -function preg_replace_callback(string|array $regex, callable $callback, string|array $subject, int $limit = -1, &$count = null, int $flags = 0): string|array|null {} +function preg_replace_callback(string|array $pattern, callable $callback, string|array $subject, int $limit = -1, &$count = null, int $flags = 0): string|array|null {} /** @param int $count */ function preg_replace_callback_array(array $pattern, string|array $subject, int $limit = -1, &$count = null, int $flags = 0): string|array|null {} function preg_split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array|false {} -function preg_quote(string $str, ?string $delim_char = null): string {} +function preg_quote(string $str, ?string $delimiter = null): string {} -function preg_grep(string $regex, array $input, int $flags = 0): array|false {} +function preg_grep(string $pattern, array $array, int $flags = 0): array|false {} function preg_last_error(): int {} diff --git a/ext/pcre/php_pcre_arginfo.h b/ext/pcre/php_pcre_arginfo.h index d1d816cfa0f39..c53f35559e36b 100644 --- a/ext/pcre/php_pcre_arginfo.h +++ b/ext/pcre/php_pcre_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8270971708afa7fa9d82bec0f84c66cc8283f17d */ + * Stub hash: 2e5a9edc9635edd4f5a00e9d888fb34c1746a5b8 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_match, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, subpatterns, "null") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, matches, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -12,14 +12,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_match_all, 0, 2, MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_NULL) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, subpatterns, "null") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, matches, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_replace, 0, 3, MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_NULL) - ZEND_ARG_TYPE_MASK(0, regex, MAY_BE_STRING|MAY_BE_ARRAY, NULL) - ZEND_ARG_TYPE_MASK(0, replace, MAY_BE_STRING|MAY_BE_ARRAY, NULL) + ZEND_ARG_TYPE_MASK(0, pattern, MAY_BE_STRING|MAY_BE_ARRAY, NULL) + ZEND_ARG_TYPE_MASK(0, replacement, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_MASK(0, subject, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "-1") ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, count, "null") @@ -28,7 +28,7 @@ ZEND_END_ARG_INFO() #define arginfo_preg_filter arginfo_preg_replace ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_replace_callback, 0, 3, MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_NULL) - ZEND_ARG_TYPE_MASK(0, regex, MAY_BE_STRING|MAY_BE_ARRAY, NULL) + ZEND_ARG_TYPE_MASK(0, pattern, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_ARG_TYPE_MASK(0, subject, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "-1") @@ -53,12 +53,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_preg_quote, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, delim_char, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, delimiter, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_grep, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) - ZEND_ARG_TYPE_INFO(0, regex, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, input, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() diff --git a/ext/pcre/tests/bug21732.phpt b/ext/pcre/tests/bug21732.phpt index 6d162d159bcb7..02a13713e2edd 100644 --- a/ext/pcre/tests/bug21732.phpt +++ b/ext/pcre/tests/bug21732.phpt @@ -17,7 +17,7 @@ try { var_dump(preg_replace_callback("/(ab)(cd)(e)/", array(new foo(), "cb"), 'abcde')); ?> --EXPECT-- -preg_replace(): Argument #1 ($regex) must be of type array when argument #2 ($replace) is an array, string given +preg_replace(): Argument #1 ($pattern) must be of type array when argument #2 ($replacement) is an array, string given array(4) { [0]=> string(5) "abcde" diff --git a/ext/pcre/tests/preg_grep_error1.phpt b/ext/pcre/tests/preg_grep_error1.phpt index 1215c24f009c3..3079c0b4b0249 100644 --- a/ext/pcre/tests/preg_grep_error1.phpt +++ b/ext/pcre/tests/preg_grep_error1.phpt @@ -56,7 +56,7 @@ Warning: preg_grep(): Unknown modifier 'F' in %spreg_grep_error1.php on line %d bool(false) Arg value is Array -preg_grep(): Argument #1 ($regex) must be of type string, array given +preg_grep(): Argument #1 ($pattern) must be of type string, array given Arg value is /[a-zA-Z]/ array(2) { @@ -65,5 +65,5 @@ array(2) { [2]=> string(4) "test" } -preg_grep(): Argument #1 ($regex) must be of type string, stdClass given +preg_grep(): Argument #1 ($pattern) must be of type string, stdClass given Done diff --git a/ext/pcre/tests/preg_match_all_error3.phpt b/ext/pcre/tests/preg_match_all_error3.phpt index 11427b7c68933..a78619bdd72bd 100644 --- a/ext/pcre/tests/preg_match_all_error3.phpt +++ b/ext/pcre/tests/preg_match_all_error3.phpt @@ -17,7 +17,7 @@ echo "Done"; --EXPECTF-- *** Testing preg_match_all() : error conditions *** -Fatal error: Uncaught Error: preg_match_all(): Argument #3 ($subpatterns) cannot be passed by reference in %s:%d +Fatal error: Uncaught Error: preg_match_all(): Argument #3 ($matches) cannot be passed by reference in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/ext/pcre/tests/preg_replace_error1.phpt b/ext/pcre/tests/preg_replace_error1.phpt index e654240f37f84..ccd3554745606 100644 --- a/ext/pcre/tests/preg_replace_error1.phpt +++ b/ext/pcre/tests/preg_replace_error1.phpt @@ -56,4 +56,4 @@ string(1) "a" Arg value is /[a-zA-Z]/ string(1) "1" -preg_replace(): Argument #1 ($regex) must be of type array|string, stdClass given +preg_replace(): Argument #1 ($pattern) must be of type array|string, stdClass given diff --git a/ext/pcre/tests/preg_replace_error2.phpt b/ext/pcre/tests/preg_replace_error2.phpt index c4503aafd198d..4b162061b3332 100644 --- a/ext/pcre/tests/preg_replace_error2.phpt +++ b/ext/pcre/tests/preg_replace_error2.phpt @@ -35,6 +35,6 @@ Arg value is: this is a string string(64) "this is a stringthis is a stringthis is a stringthis is a string" Arg value is: Array -preg_replace(): Argument #1 ($regex) must be of type array when argument #2 ($replace) is an array, string given -preg_replace(): Argument #2 ($replace) must be of type array|string, stdClass given +preg_replace(): Argument #1 ($pattern) must be of type array when argument #2 ($replacement) is an array, string given +preg_replace(): Argument #2 ($replacement) must be of type array|string, stdClass given Done diff --git a/ext/standard/tests/streams/bug61115.phpt b/ext/standard/tests/streams/bug61115.phpt index cb11e23d38014..9dfc27a9438dc 100644 --- a/ext/standard/tests/streams/bug61115.phpt +++ b/ext/standard/tests/streams/bug61115.phpt @@ -14,4 +14,4 @@ try { } ?> --EXPECT-- -preg_replace(): Argument #2 ($replace) must be of type array|string, Closure given +preg_replace(): Argument #2 ($replacement) must be of type array|string, Closure given diff --git a/sapi/cli/tests/006.phpt b/sapi/cli/tests/006.phpt index 77a5667bda82f..3a55f998443c0 100644 --- a/sapi/cli/tests/006.phpt +++ b/sapi/cli/tests/006.phpt @@ -70,7 +70,7 @@ string(%d) "Extension [ extension #%d pcre version %s ] { - Parameters [5] { Parameter #0 [ string $pattern ] Parameter #1 [ string $subject ] - Parameter #2 [ &$subpatterns = null ] + Parameter #2 [ &$matches = null ] Parameter #3 [ int $flags = 0 ] Parameter #4 [ int $offset = 0 ] } @@ -81,7 +81,7 @@ string(%d) "Extension [ extension #%d pcre version %s ] { - Parameters [5] { Parameter #0 [ string $pattern ] Parameter #1 [ string $subject ] - Parameter #2 [ &$subpatterns = null ] + Parameter #2 [ &$matches = null ] Parameter #3 [ int $flags = 0 ] Parameter #4 [ int $offset = 0 ] } @@ -90,8 +90,8 @@ string(%d) "Extension [ extension #%d pcre version %s ] { Function [ function preg_replace ] { - Parameters [5] { - Parameter #0 [ array|string $regex ] - Parameter #1 [ array|string $replace ] + Parameter #0 [ array|string $pattern ] + Parameter #1 [ array|string $replacement ] Parameter #2 [ array|string $subject ] Parameter #3 [ int $limit = -1 ] Parameter #4 [ &$count = null ] @@ -101,8 +101,8 @@ string(%d) "Extension [ extension #%d pcre version %s ] { Function [ function preg_filter ] { - Parameters [5] { - Parameter #0 [ array|string $regex ] - Parameter #1 [ array|string $replace ] + Parameter #0 [ array|string $pattern ] + Parameter #1 [ array|string $replacement ] Parameter #2 [ array|string $subject ] Parameter #3 [ int $limit = -1 ] Parameter #4 [ &$count = null ] @@ -112,7 +112,7 @@ string(%d) "Extension [ extension #%d pcre version %s ] { Function [ function preg_replace_callback ] { - Parameters [6] { - Parameter #0 [ array|string $regex ] + Parameter #0 [ array|string $pattern ] Parameter #1 [ callable $callback ] Parameter #2 [ array|string $subject ] Parameter #3 [ int $limit = -1 ] @@ -146,15 +146,15 @@ string(%d) "Extension [ extension #%d pcre version %s ] { - Parameters [2] { Parameter #0 [ string $str ] - Parameter #1 [ ?string $delim_char = null ] + Parameter #1 [ ?string $delimiter = null ] } - Return [ string ] } Function [ function preg_grep ] { - Parameters [3] { - Parameter #0 [ string $regex ] - Parameter #1 [ array $input ] + Parameter #0 [ string $pattern ] + Parameter #1 [ array $array ] Parameter #2 [ int $flags = 0 ] } - Return [ array|false ] From 811f6dd8e5f0596cb6b3621215c1427a5f487d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 23:52:07 +0200 Subject: [PATCH 20/31] Review parameter names in ext/enchant Closes GH-6258 --- ext/enchant/enchant.stub.php | 28 ++++++++++++++-------------- ext/enchant/enchant_arginfo.h | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ext/enchant/enchant.stub.php b/ext/enchant/enchant.stub.php index e39f3cd041b29..dcd11cea38bb4 100644 --- a/ext/enchant/enchant.stub.php +++ b/ext/enchant/enchant.stub.php @@ -18,10 +18,10 @@ function enchant_broker_free(EnchantBroker $broker): bool {} function enchant_broker_get_error(EnchantBroker $broker): string|false {} /** @deprecated */ -function enchant_broker_set_dict_path(EnchantBroker $broker, int $name, string $value): bool {} +function enchant_broker_set_dict_path(EnchantBroker $broker, int $type, string $path): bool {} /** @deprecated */ -function enchant_broker_get_dict_path(EnchantBroker $broker, int $name): string|false {} +function enchant_broker_get_dict_path(EnchantBroker $broker, int $type): string|false {} function enchant_broker_list_dicts(EnchantBroker $broker): array {} @@ -30,7 +30,7 @@ function enchant_broker_request_dict(EnchantBroker $broker, string $tag): Enchan function enchant_broker_request_pwl_dict(EnchantBroker $broker, string $filename): EnchantDictionary|false {} /** @deprecated */ -function enchant_broker_free_dict(EnchantDictionary $dict): bool {} +function enchant_broker_free_dict(EnchantDictionary $dictionary): bool {} function enchant_broker_dict_exists(EnchantBroker $broker, string $tag): bool {} @@ -39,32 +39,32 @@ function enchant_broker_set_ordering(EnchantBroker $broker, string $tag, string function enchant_broker_describe(EnchantBroker $broker): array {} /** @param array $suggestions */ -function enchant_dict_quick_check(EnchantDictionary $dict, string $word, &$suggestions = null): bool {} +function enchant_dict_quick_check(EnchantDictionary $dictionary, string $word, &$suggestions = null): bool {} -function enchant_dict_check(EnchantDictionary $dict, string $word): bool {} +function enchant_dict_check(EnchantDictionary $dictionary, string $word): bool {} -function enchant_dict_suggest(EnchantDictionary $dict, string $word): array {} +function enchant_dict_suggest(EnchantDictionary $dictionary, string $word): array {} -function enchant_dict_add(EnchantDictionary $dict, string $word): void {} +function enchant_dict_add(EnchantDictionary $dictionary, string $word): void {} /** * @alias enchant_dict_add * @deprecated */ -function enchant_dict_add_to_personal(EnchantDictionary $dict, string $word): void {} +function enchant_dict_add_to_personal(EnchantDictionary $dictionary, string $word): void {} -function enchant_dict_add_to_session(EnchantDictionary $dict, string $word): void {} +function enchant_dict_add_to_session(EnchantDictionary $dictionary, string $word): void {} -function enchant_dict_is_added(EnchantDictionary $dict, string $word): bool {} +function enchant_dict_is_added(EnchantDictionary $dictionary, string $word): bool {} /** * @alias enchant_dict_is_added * @deprecated */ -function enchant_dict_is_in_session(EnchantDictionary $dict, string $word): bool {} +function enchant_dict_is_in_session(EnchantDictionary $dictionary, string $word): bool {} -function enchant_dict_store_replacement(EnchantDictionary $dict, string $mis, string $cor): void {} +function enchant_dict_store_replacement(EnchantDictionary $dictionary, string $misspelled, string $correct): void {} -function enchant_dict_get_error(EnchantDictionary $dict): string|false {} +function enchant_dict_get_error(EnchantDictionary $dictionary): string|false {} -function enchant_dict_describe(EnchantDictionary $dict): array {} +function enchant_dict_describe(EnchantDictionary $dictionary): array {} diff --git a/ext/enchant/enchant_arginfo.h b/ext/enchant/enchant_arginfo.h index 94fdb781a4512..34fa122b54fdb 100644 --- a/ext/enchant/enchant_arginfo.h +++ b/ext/enchant/enchant_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 22c47f0b30f6952a42546c403fbd2e92836661fa */ + * Stub hash: 31f7c4cd39e58d6474b90acd65f4b7bda7a6ddf3 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_enchant_broker_init, 0, 0, EnchantBroker, MAY_BE_FALSE) ZEND_END_ARG_INFO() @@ -14,13 +14,13 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_broker_set_dict_path, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, broker, EnchantBroker, 0) - ZEND_ARG_TYPE_INFO(0, name, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_enchant_broker_get_dict_path, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, broker, EnchantBroker, 0) - ZEND_ARG_TYPE_INFO(0, name, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_broker_list_dicts, 0, 1, IS_ARRAY, 0) @@ -38,7 +38,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_enchant_broker_request_pwl_d ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_broker_free_dict, 0, 1, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_broker_dict_exists, 0, 2, _IS_BOOL, 0) @@ -55,23 +55,23 @@ ZEND_END_ARG_INFO() #define arginfo_enchant_broker_describe arginfo_enchant_broker_list_dicts ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_quick_check, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, suggestions, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_check, 0, 2, _IS_BOOL, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_suggest, 0, 2, IS_ARRAY, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_add, 0, 2, IS_VOID, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -84,17 +84,17 @@ ZEND_END_ARG_INFO() #define arginfo_enchant_dict_is_in_session arginfo_enchant_dict_check ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_store_replacement, 0, 3, IS_VOID, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) - ZEND_ARG_TYPE_INFO(0, mis, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, cor, IS_STRING, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) + ZEND_ARG_TYPE_INFO(0, misspelled, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, correct, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_enchant_dict_get_error, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_enchant_dict_describe, 0, 1, IS_ARRAY, 0) - ZEND_ARG_OBJ_INFO(0, dict, EnchantDictionary, 0) + ZEND_ARG_OBJ_INFO(0, dictionary, EnchantDictionary, 0) ZEND_END_ARG_INFO() From 4f42519571520217e65cf52e80a202031def35cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 23:20:09 +0200 Subject: [PATCH 21/31] Review parameter names in ext/exif Closes GH-6256 --- ext/exif/exif.stub.php | 10 +++++----- ext/exif/exif_arginfo.h | 12 ++++++------ ext/exif/tests/filename_empty.phpt | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ext/exif/exif.stub.php b/ext/exif/exif.stub.php index 9cc099ba2a465..9a8afe8577f3d 100644 --- a/ext/exif/exif.stub.php +++ b/ext/exif/exif.stub.php @@ -4,15 +4,15 @@ function exif_tagname(int $index): string|false {} -/** @param resource|string $filename */ -function exif_read_data($filename, ?string $sections_needed = null, bool $sub_arrays = false, bool $read_thumbnail = false): array|false {} +/** @param resource|string $file */ +function exif_read_data($file, ?string $required_sections = null, bool $as_arrays = false, bool $read_thumbnail = false): array|false {} /** - * @param resource|string $filename + * @param resource|string $file * @param int $width * @param int $height - * @param int $imagetype + * @param int $image_type */ -function exif_thumbnail($filename, &$width = null, &$height = null, &$imagetype = null): string|false {} +function exif_thumbnail($file, &$width = null, &$height = null, &$image_type = null): string|false {} function exif_imagetype(string $filename): int|false {} diff --git a/ext/exif/exif_arginfo.h b/ext/exif/exif_arginfo.h index b16f457c56d10..91dd8b0e61ab6 100644 --- a/ext/exif/exif_arginfo.h +++ b/ext/exif/exif_arginfo.h @@ -1,22 +1,22 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d8cb3719a7de74b27b306c30b6be0af0647b6af4 */ + * Stub hash: ef23ff502ea9658af29e50d57366c281f7a7eb6c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_exif_tagname, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_exif_read_data, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) - ZEND_ARG_INFO(0, filename) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, sections_needed, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, sub_arrays, _IS_BOOL, 0, "false") + ZEND_ARG_INFO(0, file) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, required_sections, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, as_arrays, _IS_BOOL, 0, "false") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, read_thumbnail, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_exif_thumbnail, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, filename) + ZEND_ARG_INFO(0, file) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, width, "null") ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, height, "null") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, imagetype, "null") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, image_type, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_exif_imagetype, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) diff --git a/ext/exif/tests/filename_empty.phpt b/ext/exif/tests/filename_empty.phpt index b2f58ae3c5ea4..fb2c90fdb7f90 100644 --- a/ext/exif/tests/filename_empty.phpt +++ b/ext/exif/tests/filename_empty.phpt @@ -29,7 +29,7 @@ try { ?> --EXPECT-- -exif_read_data(): Argument #1 ($filename) cannot be empty -exif_thumbnail(): Argument #1 ($filename) cannot be empty -exif_read_data(): Argument #1 ($filename) must not contain any null bytes -exif_thumbnail(): Argument #1 ($filename) must not contain any null bytes +exif_read_data(): Argument #1 ($file) cannot be empty +exif_thumbnail(): Argument #1 ($file) cannot be empty +exif_read_data(): Argument #1 ($file) must not contain any null bytes +exif_thumbnail(): Argument #1 ($file) must not contain any null bytes From ae77c7b057c548cb352cd78d60734c273101ea16 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 12:08:00 +0200 Subject: [PATCH 22/31] Return correct result code for division by zero Turns out we do need to return FAILURE here on div by zero exception. Use a three-way return value from div_function_base. Fixes oss-fuzz #25975. --- Zend/tests/div_by_zero_in_static.phpt | 11 +++++++++++ Zend/zend_operators.c | 23 ++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 Zend/tests/div_by_zero_in_static.phpt diff --git a/Zend/tests/div_by_zero_in_static.phpt b/Zend/tests/div_by_zero_in_static.phpt new file mode 100644 index 0000000000000..2d7a908e73986 --- /dev/null +++ b/Zend/tests/div_by_zero_in_static.phpt @@ -0,0 +1,11 @@ +--TEST-- +Division by zero in static +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught DivisionByZeroError: Division by zero in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 5f9dbe3d3ce01..e7fb82e04fe46 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1253,7 +1253,9 @@ ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *o } /* }}} */ -static zend_result ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /* {{{ */ +/* Returns SUCCESS/FAILURE/TYPES_NOT_HANDLED */ +#define TYPES_NOT_HANDLED 1 +static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /* {{{ */ { zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); @@ -1290,14 +1292,14 @@ static zend_result ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2)); return SUCCESS; } else { - return FAILURE; + return TYPES_NOT_HANDLED; } division_by_0: if (result != op1) { ZVAL_UNDEF(result); } zend_throw_error(zend_ce_division_by_zero_error, "Division by zero"); - return SUCCESS; + return FAILURE; } /* }}} */ @@ -1305,8 +1307,10 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o { ZVAL_DEREF(op1); ZVAL_DEREF(op2); - if (div_function_base(result, op1, op2) == SUCCESS) { - return SUCCESS; + + int retval = div_function_base(result, op1, op2); + if (retval != TYPES_NOT_HANDLED) { + return retval; } ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV); @@ -1325,12 +1329,9 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o zval_ptr_dtor(result); } - if (div_function_base(result, &op1_copy, &op2_copy) == SUCCESS) { - return SUCCESS; - } - - ZEND_ASSERT(0 && "Operation must succeed"); - return FAILURE; + retval = div_function_base(result, &op1_copy, &op2_copy); + ZEND_ASSERT(retval != TYPES_NOT_HANDLED && "Types should be handled"); + return retval; } /* }}} */ From c9c7820f74e5658fe3d7735424e00ea3916897c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 1 Oct 2020 20:12:22 +0200 Subject: [PATCH 23/31] Review parameter names in ext/ftp Closes GH-6254 --- ext/ftp/ftp.stub.php | 42 ++++++++++++------------ ext/ftp/ftp_arginfo.h | 75 +++++++++++++++++++++---------------------- 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/ext/ftp/ftp.stub.php b/ext/ftp/ftp.stub.php index 17b047399572a..f4812655a4c50 100644 --- a/ext/ftp/ftp.stub.php +++ b/ext/ftp/ftp.stub.php @@ -3,11 +3,11 @@ /** @generate-function-entries */ /** @return resource|false */ -function ftp_connect(string $host, int $port = 21, int $timeout = 90) {} +function ftp_connect(string $hostname, int $port = 21, int $timeout = 90) {} #ifdef HAVE_FTP_SSL /** @return resource|false */ -function ftp_ssl_connect(string $host, int $port = 21, int $timeout = 90) {} +function ftp_ssl_connect(string $hostname, int $port = 21, int $timeout = 90) {} #endif /** @param resource $ftp */ @@ -35,7 +35,7 @@ function ftp_mkdir($ftp, string $directory): string|false {} function ftp_rmdir($ftp, string $directory): bool {} /** @param resource $ftp */ -function ftp_chmod($ftp, int $mode, string $filename): int|false {} +function ftp_chmod($ftp, int $permissions, string $filename): int|false {} /** * @param resource $ftp @@ -47,7 +47,7 @@ function ftp_alloc($ftp, int $size, &$response = null): bool {} function ftp_nlist($ftp, string $directory): array|false {} /** @param resource $ftp */ -function ftp_rawlist($ftp, string $directory, bool $recurse = false): array|false {} +function ftp_rawlist($ftp, string $directory, bool $recursive = false): array|false {} /** @param resource $ftp */ function ftp_mlsd($ftp, string $directory): array|false {} @@ -57,48 +57,48 @@ function ftp_systype($ftp): string|false {} /** * @param resource $ftp - * @param resource $fp + * @param resource $stream */ -function ftp_fget($ftp, $fp, string $remote_file, int $mode = FTP_BINARY, int $resumepos = 0): bool {} +function ftp_fget($ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {} /** * @param resource $ftp - * @param resource $fp + * @param resource $stream */ -function ftp_nb_fget($ftp, $fp, string $remote_file, int $mode = FTP_BINARY, int $resumpos = 0): int {} +function ftp_nb_fget($ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {} /** @param resource $ftp */ -function ftp_pasv($ftp, bool $pasv): bool {} +function ftp_pasv($ftp, bool $enable): bool {} /** @param resource $ftp */ -function ftp_get($ftp, string $local_file, string $remote_file, int $mode = FTP_BINARY, int $resumepos = 0): bool {} +function ftp_get($ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {} /** @param resource $ftp */ -function ftp_nb_get($ftp, string $local_file, string $remote_file, int $mode = FTP_BINARY, int $resume_pos = 0): int {} +function ftp_nb_get($ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {} /** @param resource $ftp */ function ftp_nb_continue($ftp): int {} /** * @param resource $ftp - * @param resource $fp + * @param resource $stream */ -function ftp_fput($ftp, string $remote_file, $fp, int $mode = FTP_BINARY, int $startpos = 0): bool {} +function ftp_fput($ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): bool {} /** * @param resource $ftp - * @param resource $fp + * @param resource $stream */ -function ftp_nb_fput($ftp, string $remote_file, $fp, int $mode = FTP_BINARY, int $startpos = 0): int {} +function ftp_nb_fput($ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): int {} /** @param resource $ftp */ -function ftp_put($ftp, string $remote_file, string $local_file, int $mode = FTP_BINARY, int $startpos = 0): bool {} +function ftp_put($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): bool {} /** @param resource $ftp */ -function ftp_append($ftp, string $remove_file, string $local_file, int $mode = FTP_BINARY): bool {} +function ftp_append($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY): bool {} /** @param resource $ftp */ -function ftp_nb_put($ftp, string $remote_file, string $local_file, int $mode = FTP_BINARY, int $startpos = 0): int|false {} +function ftp_nb_put($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): int|false {} /** @param resource $ftp */ function ftp_size($ftp, string $filename): int {} @@ -107,13 +107,13 @@ function ftp_size($ftp, string $filename): int {} function ftp_mdtm($ftp, string $filename): int {} /** @param resource $ftp */ -function ftp_rename($ftp, string $src, string $dest): bool {} +function ftp_rename($ftp, string $from, string $to): bool {} /** @param resource $ftp */ -function ftp_delete($ftp, string $file): bool {} +function ftp_delete($ftp, string $filename): bool {} /** @param resource $ftp */ -function ftp_site($ftp, string $cmd): bool {} +function ftp_site($ftp, string $command): bool {} /** @param resource $ftp */ function ftp_close($ftp): bool {} diff --git a/ext/ftp/ftp_arginfo.h b/ext/ftp/ftp_arginfo.h index b5f160f74c65a..e1a9d770bc34b 100644 --- a/ext/ftp/ftp_arginfo.h +++ b/ext/ftp/ftp_arginfo.h @@ -1,15 +1,15 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7cf8b5776e7d2ad943683d1f1c43d44b85dea7a1 */ + * Stub hash: 4957601533b387d70ebb15811821fc06507cdbc2 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_connect, 0, 0, 1) - ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "21") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_LONG, 0, "90") ZEND_END_ARG_INFO() #if defined(HAVE_FTP_SSL) ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_ssl_connect, 0, 0, 1) - ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "21") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_LONG, 0, "90") ZEND_END_ARG_INFO() @@ -53,7 +53,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_chmod, 0, 3, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, permissions, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -71,7 +71,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_rawlist, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_INFO(0, ftp) ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, recurse, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, recursive, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() #define arginfo_ftp_mlsd arginfo_ftp_nlist @@ -80,39 +80,39 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fget, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_INFO(0, fp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) + ZEND_ARG_INFO(0, stream) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resumepos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fget, 0, 3, IS_LONG, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_INFO(0, fp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) + ZEND_ARG_INFO(0, stream) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resumpos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_pasv, 0, 2, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, pasv, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_get, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, local_file, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resumepos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_get, 0, 3, IS_LONG, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, local_file, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resume_pos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_continue, 0, 1, IS_LONG, 0) @@ -121,41 +121,41 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fput, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) - ZEND_ARG_INFO(0, fp) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) + ZEND_ARG_INFO(0, stream) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, startpos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fput, 0, 3, IS_LONG, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) - ZEND_ARG_INFO(0, fp) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) + ZEND_ARG_INFO(0, stream) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, startpos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_put, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, local_file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, startpos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_append, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, remove_file, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, local_file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_nb_put, 0, 3, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, remote_file, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, local_file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, startpos, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_size, 0, 2, IS_LONG, 0) @@ -167,19 +167,16 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_rename, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, src, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, dest, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, from, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, to, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_delete, 0, 2, _IS_BOOL, 0) ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, file, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_site, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, ftp) - ZEND_ARG_TYPE_INFO(0, cmd, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_ftp_site arginfo_ftp_exec #define arginfo_ftp_close arginfo_ftp_cdup From bf6873a18e3b6b00f82a645c0893a281ae8eadb8 Mon Sep 17 00:00:00 2001 From: "K.Kosako" Date: Mon, 21 Sep 2020 12:58:29 +0900 Subject: [PATCH 24/31] Fix out-of-bounds write Fixes CVE-2020-26159. Backported from . --- ext/mbstring/oniguruma/src/regcomp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mbstring/oniguruma/src/regcomp.c b/ext/mbstring/oniguruma/src/regcomp.c index 69d4b95f95214..4f68af234529d 100644 --- a/ext/mbstring/oniguruma/src/regcomp.c +++ b/ext/mbstring/oniguruma/src/regcomp.c @@ -5603,7 +5603,7 @@ concat_opt_exact_str(OptStr* to, UChar* s, UChar* end, OnigEncoding enc) for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) { len = enclen(enc, p); - if (i + len > OPT_EXACT_MAXLEN) break; + if (i + len >= OPT_EXACT_MAXLEN) break; for (j = 0; j < len && p < end; j++) to->s[i++] = *p++; } From 2e32a0954147260a156ba6c196e4cd8df41bc869 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 14:40:11 +0200 Subject: [PATCH 25/31] Add gen_stub --legacy flag This flag generates an arginfo file that discards all type and default value information. As such, it is compatible with old (and very old) PHP versions. Intended for use by extensions to generate one arginfo file for PHP 8 and one for older versions. --- build/gen_stub.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index bd8b33759fcdb..4f3a8514b491f 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -31,7 +31,8 @@ function processStubFile(string $stubFile, Context $context) { throw new Exception("File $stubFile does not exist"); } - $arginfoFile = str_replace('.stub.php', '', $stubFile) . '_arginfo.h'; + $arginfoFile = str_replace('.stub.php', '', $stubFile) + . ($context->legacy ? '_legacy' : '') . '_arginfo.h'; $stubCode = file_get_contents($stubFile); $stubHash = computeStubHash($stubCode); $oldStubHash = extractStubHash($arginfoFile); @@ -42,6 +43,12 @@ function processStubFile(string $stubFile, Context $context) { initPhpParser(); $fileInfo = parseStubFile($stubCode); + if ($context->legacy) { + foreach ($fileInfo->getAllFuncInfos() as $funcInfo) { + $funcInfo->discardInfoForOldPhpVersions(); + } + } + $arginfoCode = generateArgInfoCode($fileInfo, $stubHash); file_put_contents($arginfoFile, $arginfoCode); @@ -534,6 +541,14 @@ private function getFlagsAsString(): string return $flags; } + + public function discardInfoForOldPhpVersions(): void { + $this->return->type = null; + foreach ($this->args as $arg) { + $arg->type = null; + $arg->defaultValue = null; + } + } } class ClassInfo { @@ -1148,10 +1163,11 @@ function initPhpParser() { } $optind = null; -$options = getopt("f", ["force-regeneration", "parameter-stats"], $optind); +$options = getopt("f", ["force-regeneration", "parameter-stats", "legacy"], $optind); $context = new Context; $printParameterStats = isset($options["parameter-stats"]); +$context->legacy = isset($options["legacy"]); $context->forceRegeneration = isset($options["f"]) || isset($options["force-regeneration"]) || $printParameterStats; From 924ac2b98ae558617708180767ae512aa0c13f7a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 17:07:46 +0200 Subject: [PATCH 26/31] Add partial namespace support to gen_stub --- build/gen_stub.php | 198 ++++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 73 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 4f3a8514b491f..e2c6bb2eb225b 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -337,30 +337,73 @@ public function getDefaultValueString(): string { } } -class FunctionName { - /** @var string|null */ +interface FunctionOrMethodName { + public function getDeclaration(): string; + public function getArgInfoName(): string; + public function __toString(): string; +} + +class FunctionName implements FunctionOrMethodName { + /** @var Name */ + private $name; + + public function __construct(Name $name) { + $this->name = $name; + } + + public function getNamespace(): ?string { + if ($this->name->isQualified()) { + return $this->name->slice(0, -1)->toString(); + } + return null; + } + + public function getShortName(): string { + return $this->name->getLast(); + } + + public function getNonNamespacedName(): string { + if ($this->name->isQualified()) { + throw new Exception("Namespaced name not supported here"); + } + return $this->name->toString(); + } + + public function getDeclaration(): string { + return "ZEND_FUNCTION({$this->name->getLast()});\n"; + } + + public function getArgInfoName(): string { + $underscoreName = implode('_', $this->name->parts); + return "arginfo_$underscoreName"; + } + + public function __toString(): string { + return $this->name->toString(); + } +} + +class MethodName implements FunctionOrMethodName { + /** @var string */ public $className; /** @var string */ public $name; - public function __construct(?string $className, string $name) - { + public function __construct(string $className, string $name) { $this->className = $className; $this->name = $name; } - public function getDeclaration(): string - { - if ($this->className) { - return "ZEND_METHOD($this->className, $this->name);\n"; - } + public function getDeclaration(): string { + return "ZEND_METHOD($this->className, $this->name);\n"; + } - return "ZEND_FUNCTION($this->name);\n"; + public function getArgInfoName(): string { + return "arginfo_class_{$this->className}_{$this->name}"; } - public function __toString() - { - return $this->className ? "$this->className::$this->name" : $this->name; + public function __toString(): string { + return "$this->className::$this->name"; } } @@ -382,7 +425,7 @@ public function equals(ReturnInfo $other): bool { } class FuncInfo { - /** @var FunctionName */ + /** @var FunctionOrMethodName */ public $name; /** @var int */ public $flags; @@ -402,10 +445,10 @@ class FuncInfo { public $cond; public function __construct( - FunctionName $name, + FunctionOrMethodName $name, int $flags, ?string $aliasType, - ?FunctionName $alias, + ?FunctionOrMethodName $alias, bool $isDeprecated, array $args, ReturnInfo $return, @@ -440,10 +483,7 @@ public function equalsApartFromName(FuncInfo $other): bool { } public function getArgInfoName(): string { - if ($this->name->className) { - return 'arginfo_class_' . $this->name->className . '_' . $this->name->name; - } - return 'arginfo_' . $this->name->name; + return $this->name->getArgInfoName(); } public function getDeclarationKey(): string @@ -465,18 +505,21 @@ public function getDeclaration(): ?string } public function getFunctionEntry(): string { - if ($this->name->className) { + if ($this->name instanceof MethodName) { if ($this->alias) { - if ($this->alias->className) { + if ($this->alias instanceof MethodName) { return sprintf( "\tZEND_MALIAS(%s, %s, %s, %s, %s)\n", $this->alias->className, $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString() ); - } else { + } else if ($this->alias instanceof FunctionName) { return sprintf( "\tZEND_ME_MAPPING(%s, %s, %s, %s)\n", - $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString() + $this->name->name, $this->alias->getNonNamespacedName(), + $this->getArgInfoName(), $this->getFlagsAsString() ); + } else { + throw new Error("Cannot happen"); } } else { if ($this->flags & Class_::MODIFIER_ABSTRACT) { @@ -491,26 +534,37 @@ public function getFunctionEntry(): string { $this->name->className, $this->name->name, $this->getArgInfoName(), $this->getFlagsAsString() ); } - } else { + } else if ($this->name instanceof FunctionName) { + $namespace = $this->name->getNamespace(); + $shortName = $this->name->getShortName(); + if ($this->alias && $this->isDeprecated) { return sprintf( "\tZEND_DEP_FALIAS(%s, %s, %s)\n", - $this->name, $this->alias->name, $this->getArgInfoName() + $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() ); } if ($this->alias) { return sprintf( "\tZEND_FALIAS(%s, %s, %s)\n", - $this->name, $this->alias->name, $this->getArgInfoName() + $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() ); } if ($this->isDeprecated) { - return sprintf("\tZEND_DEP_FE(%s, %s)\n", $this->name, $this->getArgInfoName()); + return sprintf("\tZEND_DEP_FE(%s, %s)\n", $shortName, $this->getArgInfoName()); } - return sprintf("\tZEND_FE(%s, %s)\n", $this->name, $this->getArgInfoName()); + if ($namespace) { + return sprintf( + "\tZEND_NS_FE(\"%s\", %s, %s)\n", + $namespace, $shortName, $this->getArgInfoName()); + } else { + return sprintf("\tZEND_FE(%s, %s)\n", $shortName, $this->getArgInfoName()); + } + } else { + throw new Error("Cannot happen"); } } @@ -565,18 +619,11 @@ public function __construct(string $name, array $funcInfos) { class FileInfo { /** @var FuncInfo[] */ - public $funcInfos; + public $funcInfos = []; /** @var ClassInfo[] */ - public $classInfos; + public $classInfos = []; /** @var bool */ - public $generateFunctionEntries; - - public function __construct( - array $funcInfos, array $classInfos, bool $generateFunctionEntries) { - $this->funcInfos = $funcInfos; - $this->classInfos = $classInfos; - $this->generateFunctionEntries = $generateFunctionEntries; - } + public $generateFunctionEntries = false; /** * @return iterable @@ -646,7 +693,7 @@ function parseDocComment(DocComment $comment): array { function parseFunctionLike( PrettyPrinterAbstract $prettyPrinter, - FunctionName $name, + FunctionOrMethodName $name, int $flags, Node\FunctionLike $func, ?string $cond @@ -672,9 +719,9 @@ function parseFunctionLike( $aliasType = $tag->name; $aliasParts = explode("::", $tag->getValue()); if (count($aliasParts) === 1) { - $alias = new FunctionName(null, $aliasParts[0]); + $alias = new FunctionName(new Name($aliasParts[0])); } else { - $alias = new FunctionName($aliasParts[0], $aliasParts[1]); + $alias = new MethodName($aliasParts[0], $aliasParts[1]); } } else if ($tag->name === 'deprecated') { $isDeprecated = true; @@ -814,46 +861,27 @@ function getFileDocComment(array $stmts): ?DocComment { return null; } -function parseStubFile(string $code): FileInfo { - $lexer = new PhpParser\Lexer(); - $parser = new PhpParser\Parser\Php7($lexer); - $nodeTraverser = new PhpParser\NodeTraverser; - $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); - $prettyPrinter = new class extends Standard { - protected function pName_FullyQualified(Name\FullyQualified $node) { - return implode('\\', $node->parts); - } - }; - - $stmts = $parser->parse($code); - $nodeTraverser->traverse($stmts); - - $generateFunctionEntries = false; - $fileDocComment = getFileDocComment($stmts); - if ($fileDocComment) { - if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) { - $generateFunctionEntries = true; - } - } - - $funcInfos = []; - $classInfos = []; +function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstract $prettyPrinter) { $conds = []; foreach ($stmts as $stmt) { - $cond = handlePreprocessorConditions($conds, $stmt); if ($stmt instanceof Stmt\Nop) { continue; } + if ($stmt instanceof Stmt\Namespace_) { + handleStatements($fileInfo, $stmt->stmts, $prettyPrinter); + continue; + } + + $cond = handlePreprocessorConditions($conds, $stmt); if ($stmt instanceof Stmt\Function_) { - $funcInfos[] = parseFunctionLike( + $fileInfo->funcInfos[] = parseFunctionLike( $prettyPrinter, - new FunctionName(null, $stmt->name->toString()), + new FunctionName($stmt->namespacedName), 0, $stmt, $cond ); - continue; } @@ -881,21 +909,45 @@ protected function pName_FullyQualified(Name\FullyQualified $node) { $methodInfos[] = parseFunctionLike( $prettyPrinter, - new FunctionName($className, $classStmt->name->toString()), + new MethodName($className, $classStmt->name->toString()), $flags, $classStmt, $cond ); } - $classInfos[] = new ClassInfo($className, $methodInfos); + $fileInfo->classInfos[] = new ClassInfo($className, $methodInfos); continue; } throw new Exception("Unexpected node {$stmt->getType()}"); } +} + +function parseStubFile(string $code): FileInfo { + $lexer = new PhpParser\Lexer(); + $parser = new PhpParser\Parser\Php7($lexer); + $nodeTraverser = new PhpParser\NodeTraverser; + $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); + $prettyPrinter = new class extends Standard { + protected function pName_FullyQualified(Name\FullyQualified $node) { + return implode('\\', $node->parts); + } + }; + + $stmts = $parser->parse($code); + $nodeTraverser->traverse($stmts); + + $fileInfo = new FileInfo; + $fileDocComment = getFileDocComment($stmts); + if ($fileDocComment) { + if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) { + $fileInfo->generateFunctionEntries = true; + } + } - return new FileInfo($funcInfos, $classInfos, $generateFunctionEntries); + handleStatements($fileInfo, $stmts, $prettyPrinter); + return $fileInfo; } function funcInfoToCode(FuncInfo $funcInfo): string { From dfa6d1c22ef55a9e288a63a20a869f218fb7a7a6 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 17:21:16 +0200 Subject: [PATCH 27/31] Support specifying linkage for generate-function-entries The linkage can be specified as the argument to the @generate-function-entries tag. Test this on zend_test. --- build/gen_stub.php | 15 ++++++++++----- ext/zend_test/test.c | 34 +++++++++++++++++----------------- ext/zend_test/test.stub.php | 2 +- ext/zend_test/test_arginfo.h | 34 +++++++++++++++++----------------- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index e2c6bb2eb225b..56106dec90284 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -624,6 +624,8 @@ class FileInfo { public $classInfos = []; /** @var bool */ public $generateFunctionEntries = false; + /** @var string */ + public $declarationPrefix = ""; /** * @return iterable @@ -941,8 +943,12 @@ protected function pName_FullyQualified(Name\FullyQualified $node) { $fileInfo = new FileInfo; $fileDocComment = getFileDocComment($stmts); if ($fileDocComment) { - if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) { - $fileInfo->generateFunctionEntries = true; + $fileTags = parseDocComment($fileDocComment); + foreach ($fileTags as $tag) { + if ($tag->name === 'generate-function-entries') { + $fileInfo->generateFunctionEntries = true; + $fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : ""; + } } } @@ -1110,15 +1116,14 @@ function (FuncInfo $funcInfo) use(&$generatedFuncInfos) { $generatedFunctionDeclarations = []; $code .= generateCodeWithConditions( $fileInfo->getAllFuncInfos(), "", - function (FuncInfo $funcInfo) use(&$generatedFunctionDeclarations) { + function (FuncInfo $funcInfo) use($fileInfo, &$generatedFunctionDeclarations) { $key = $funcInfo->getDeclarationKey(); if (isset($generatedFunctionDeclarations[$key])) { return null; } $generatedFunctionDeclarations[$key] = true; - - return $funcInfo->getDeclaration(); + return $fileInfo->declarationPrefix . $funcInfo->getDeclaration(); } ); diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 92b8e4cf6a815..13781e32be75f 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -51,7 +51,7 @@ static zend_class_entry *zend_test_trait; static zend_class_entry *zend_test_attribute; static zend_object_handlers zend_test_class_handlers; -ZEND_FUNCTION(zend_test_func) +static ZEND_FUNCTION(zend_test_func) { RETVAL_STR_COPY(EX(func)->common.function_name); @@ -62,23 +62,23 @@ ZEND_FUNCTION(zend_test_func) EX(func) = NULL; } -ZEND_FUNCTION(zend_test_array_return) +static ZEND_FUNCTION(zend_test_array_return) { ZEND_PARSE_PARAMETERS_NONE(); } -ZEND_FUNCTION(zend_test_nullable_array_return) +static ZEND_FUNCTION(zend_test_nullable_array_return) { ZEND_PARSE_PARAMETERS_NONE(); } -ZEND_FUNCTION(zend_test_void_return) +static ZEND_FUNCTION(zend_test_void_return) { /* dummy */ ZEND_PARSE_PARAMETERS_NONE(); } -ZEND_FUNCTION(zend_test_deprecated) +static ZEND_FUNCTION(zend_test_deprecated) { zval *arg1; @@ -88,7 +88,7 @@ ZEND_FUNCTION(zend_test_deprecated) /* Create a string without terminating null byte. Must be terminated with * zend_terminate_string() before destruction, otherwise a warning is issued * in debug builds. */ -ZEND_FUNCTION(zend_create_unterminated_string) +static ZEND_FUNCTION(zend_create_unterminated_string) { zend_string *str, *res; @@ -104,7 +104,7 @@ ZEND_FUNCTION(zend_create_unterminated_string) } /* Enforce terminate null byte on string. This avoids a warning in debug builds. */ -ZEND_FUNCTION(zend_terminate_string) +static ZEND_FUNCTION(zend_terminate_string) { zend_string *str; @@ -116,7 +116,7 @@ ZEND_FUNCTION(zend_terminate_string) } /* {{{ Cause an intentional memory leak, for testing/debugging purposes */ -ZEND_FUNCTION(zend_leak_bytes) +static ZEND_FUNCTION(zend_leak_bytes) { zend_long leakbytes = 3; @@ -129,7 +129,7 @@ ZEND_FUNCTION(zend_leak_bytes) /* }}} */ /* {{{ Leak a refcounted variable */ -ZEND_FUNCTION(zend_leak_variable) +static ZEND_FUNCTION(zend_leak_variable) { zval *zv; @@ -147,7 +147,7 @@ ZEND_FUNCTION(zend_leak_variable) /* }}} */ /* Tests Z_PARAM_OBJ_OR_STR */ -ZEND_FUNCTION(zend_string_or_object) +static ZEND_FUNCTION(zend_string_or_object) { zend_string *str; zend_object *object; @@ -165,7 +165,7 @@ ZEND_FUNCTION(zend_string_or_object) /* }}} */ /* Tests Z_PARAM_OBJ_OR_STR_OR_NULL */ -ZEND_FUNCTION(zend_string_or_object_or_null) +static ZEND_FUNCTION(zend_string_or_object_or_null) { zend_string *str; zend_object *object; @@ -185,7 +185,7 @@ ZEND_FUNCTION(zend_string_or_object_or_null) /* }}} */ /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR */ -ZEND_FUNCTION(zend_string_or_stdclass) +static ZEND_FUNCTION(zend_string_or_stdclass) { zend_string *str; zend_object *object; @@ -203,7 +203,7 @@ ZEND_FUNCTION(zend_string_or_stdclass) /* }}} */ /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */ -ZEND_FUNCTION(zend_string_or_stdclass_or_null) +static ZEND_FUNCTION(zend_string_or_stdclass_or_null) { zend_string *str; zend_object *object; @@ -223,7 +223,7 @@ ZEND_FUNCTION(zend_string_or_stdclass_or_null) /* }}} */ /* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */ -ZEND_FUNCTION(zend_iterable) +static ZEND_FUNCTION(zend_iterable) { zval *arg1, *arg2; @@ -292,18 +292,18 @@ void zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t ta } } -ZEND_METHOD(_ZendTestClass, __toString) /* {{{ */ { +static ZEND_METHOD(_ZendTestClass, __toString) /* {{{ */ { RETURN_EMPTY_STRING(); } /* }}} */ /* Internal function returns bool, we return int. */ -ZEND_METHOD(_ZendTestClass, is_object) /* {{{ */ { +static ZEND_METHOD(_ZendTestClass, is_object) /* {{{ */ { RETURN_LONG(42); } /* }}} */ -ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ { +static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ { RETURN_TRUE; } /* }}} */ diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 1dd0cfec4e5b1..96e7b56921128 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -1,6 +1,6 @@ Date: Thu, 1 Oct 2020 19:02:49 +0100 Subject: [PATCH 28/31] Use a subrountine to check for valid OID strings Closes 6260 --- ext/pgsql/pgsql.c | 67 +++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 63e59b63d695d..88cf0c431eeb4 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1474,6 +1474,13 @@ PHP_FUNCTION(pg_last_notice) } /* }}} */ +static inline bool is_valid_oid_string(zend_string *oid, Oid *return_oid) +{ + char *end_ptr; + *return_oid = (Oid) strtoul(ZSTR_VAL(oid), &end_ptr, 10); + return ZSTR_VAL(oid) + ZSTR_LEN(oid) == end_ptr; +} + /* {{{ get_field_name */ static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list) { @@ -2323,10 +2330,7 @@ PHP_FUNCTION(pg_lo_create) switch (Z_TYPE_P(oid)) { case IS_STRING: { - /* TODO: Use subroutine? */ - char *end_ptr; - wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10); - if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) { + if (!is_valid_oid_string(Z_STR_P(oid), &wanted_oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2366,19 +2370,15 @@ PHP_FUNCTION(pg_lo_unlink) { zval *pgsql_link = NULL; zend_long oid_long; - char *oid_string, *end_ptr; - size_t oid_strlen; + zend_string *oid_string; PGconn *pgsql; Oid oid; zend_resource *link; int argc = ZEND_NUM_ARGS(); /* accept string type since Oid type is unsigned int */ - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "rs", &pgsql_link, &oid_string, &oid_strlen) == SUCCESS) { - /* TODO: Use subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "rS", &pgsql_link, &oid_string) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2394,11 +2394,8 @@ PHP_FUNCTION(pg_lo_unlink) oid = (Oid)oid_long; link = Z_RES_P(pgsql_link); } - else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "s", &oid_string, &oid_strlen) == SUCCESS) { - /* TODO: subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "S", &oid_string) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2438,8 +2435,9 @@ PHP_FUNCTION(pg_lo_open) { zval *pgsql_link = NULL; zend_long oid_long; - char *oid_string, *end_ptr, *mode_string; - size_t oid_strlen, mode_strlen; + zend_string *oid_string; + char *mode_string; + size_t mode_strlen; PGconn *pgsql; Oid oid; int pgsql_mode=0, pgsql_lofd; @@ -2450,10 +2448,8 @@ PHP_FUNCTION(pg_lo_open) /* accept string type since Oid is unsigned int */ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "rss", &pgsql_link, &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) { - /* TODO: Use subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + "rSs", &pgsql_link, &oid_string, &mode_string, &mode_strlen) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2470,10 +2466,8 @@ PHP_FUNCTION(pg_lo_open) link = Z_RES_P(pgsql_link); } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "ss", &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) { - /* TODO: Use subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + "Ss", &oid_string, &mode_string, &mode_strlen) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2723,10 +2717,7 @@ PHP_FUNCTION(pg_lo_import) switch (Z_TYPE_P(oid)) { case IS_STRING: { - /* TODO: Use subroutine? */ - char *end_ptr; - wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10); - if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) { + if (!is_valid_oid_string(Z_STR_P(oid), &wanted_oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2767,8 +2758,8 @@ PHP_FUNCTION(pg_lo_import) PHP_FUNCTION(pg_lo_export) { zval *pgsql_link = NULL; - char *file_out, *oid_string, *end_ptr; - size_t oid_strlen; + zend_string *oid_string; + char *file_out; size_t name_len; zend_long oid_long; Oid oid; @@ -2787,10 +2778,8 @@ PHP_FUNCTION(pg_lo_export) link = Z_RES_P(pgsql_link); } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "rsp", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) { - /* TODO: Use subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + "rSp", &pgsql_link, &oid_string, &file_out, &name_len) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); @@ -2808,10 +2797,8 @@ PHP_FUNCTION(pg_lo_export) CHECK_DEFAULT_LINK(link); } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, - "sp", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) { - /* TODO: Use subroutine? */ - oid = (Oid)strtoul(oid_string, &end_ptr, 10); - if ((oid_string+oid_strlen) != end_ptr) { + "Sp", &oid_string, &file_out, &name_len) == SUCCESS) { + if (!is_valid_oid_string(oid_string, &oid)) { /* wrong integer format */ zend_value_error("Invalid OID value passed"); RETURN_THROWS(); From 2d234d111a012e65ce210d34fb0e876d75059806 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 Oct 2020 17:53:45 +0200 Subject: [PATCH 29/31] Declare FFI\CType in namespace Now that it is supported, declare that CType is part of the FFI namespace, not a freestanding class. --- ext/ffi/ffi.stub.php | 8 ++++++++ ext/ffi/ffi_arginfo.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ext/ffi/ffi.stub.php b/ext/ffi/ffi.stub.php index 3b6bce138f7a0..1662caa41b92c 100644 --- a/ext/ffi/ffi.stub.php +++ b/ext/ffi/ffi.stub.php @@ -2,6 +2,8 @@ /** @generate-function-entries */ +namespace { + final class FFI { public static function cdef(string $code = "", ?string $lib = null): FFI {} @@ -62,6 +64,12 @@ public static function string(FFI\CData $ptr, ?int $size = null): ?string {} public static function isNull(FFI\CData $ptr): bool {} } +} + +namespace FFI { + final class CType { public function getName() : string {} } + +} diff --git a/ext/ffi/ffi_arginfo.h b/ext/ffi/ffi_arginfo.h index df1ddf8de3d42..b5162fcce7a0d 100644 --- a/ext/ffi/ffi_arginfo.h +++ b/ext/ffi/ffi_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: cf08aabbc0e1c50204772ace9285f1c5ef7a22fe */ + * Stub hash: 63219df3f7ccf823350d288bf2dfeba5291a3e51 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_cdef, 0, 0, FFI, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_STRING, 0, "\"\"") From 54435c9b43fb568590b223a24dcf582f1292a5d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 23 Sep 2020 15:34:17 +0200 Subject: [PATCH 30/31] Fix #64060: lstat_stat_variation7.phpt fails on certain file systems Closes GH-6194. --- NEWS | 6 +++++- ext/standard/tests/file/lstat_stat_variation7.phpt | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index dc39e99d07f01..b0e4d74d2810f 100644 --- a/NEWS +++ b/NEWS @@ -6,10 +6,14 @@ PHP NEWS . Fixed bug #80121 (Null pointer deref if CurlHandle directly instantiated). (Nikita) -- SPL. +- SPL: . Fixed bug #65387 (Circular references in SPL iterators are not garbage collected). (Nikita) +- Standard: + . Fixed bug #64060 (lstat_stat_variation7.phpt fails on certain file systems). + (M. Voelker, cmb) + 01 Oct 2020, PHP 8.0.0rc1 - CLI: diff --git a/ext/standard/tests/file/lstat_stat_variation7.phpt b/ext/standard/tests/file/lstat_stat_variation7.phpt index fab011dd20ad5..a5128606f4a5b 100644 --- a/ext/standard/tests/file/lstat_stat_variation7.phpt +++ b/ext/standard/tests/file/lstat_stat_variation7.phpt @@ -18,6 +18,7 @@ $old_stat = stat($file_name); clearstatcache(); $blksize = PHP_OS_FAMILY === 'Windows' ? 4096 : $old_stat['blksize']; fwrite($fh, str_repeat("Hello World", $blksize)); +fclose($fh); $new_stat = stat($file_name); // compare self stats From 107962208a19d8b6dc1a190cb25fc37614411e71 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 2 Oct 2020 17:34:07 +0200 Subject: [PATCH 31/31] add note about is_callable change --- UPGRADING | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADING b/UPGRADING index 0c15b1ecbe990..09a317da7511d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -27,6 +27,8 @@ PHP 8.0 UPGRADE NOTES . Methods with the same name as the class are no longer interpreted as constructors. The __construct() method should be used instead. . Removed ability to call non-static methods statically. + Thus `is_callable` will fail when checking for a non-static method with a + classname (must check with an object instance). . Removed (unset) cast. . Removed track_errors ini directive. This means that $php_errormsg is no longer available. The error_get_last() function may be used instead.