summaryrefslogtreecommitdiffstats
path: root/vld-upstream.patch
diff options
context:
space:
mode:
Diffstat (limited to 'vld-upstream.patch')
-rw-r--r--vld-upstream.patch299
1 files changed, 299 insertions, 0 deletions
diff --git a/vld-upstream.patch b/vld-upstream.patch
new file mode 100644
index 0000000..b57e4de
--- /dev/null
+++ b/vld-upstream.patch
@@ -0,0 +1,299 @@
+From 850d2d82c293e52cf0ef57e6cc762617fcc09979 Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Mon, 10 Oct 2022 16:47:13 +0100
+Subject: [PATCH 1/5] Fixed crash with CATCH on PHP 8.2 with 32-bit
+
+---
+ branchinfo.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/branchinfo.c b/branchinfo.c
+index 3547c1b..bddd9ff 100644
+--- a/branchinfo.c
++++ b/branchinfo.c
+@@ -113,7 +113,11 @@ void vld_branch_post_process(zend_op_array *opa, vld_branch_info *branch_info)
+ if (vld_set_in(branch_info->entry_points, i) && opa->opcodes[i].opcode == ZEND_CATCH) {
+ #if PHP_VERSION_ID >= 70300
+ # if ZEND_USE_ABS_JMP_ADDR
++# if PHP_VERSION_ID >= 80200
++ if (opa->opcodes[i].op2.jmp_addr != -1) {
++# else
+ if (opa->opcodes[i].op2.jmp_addr != NULL) {
++# endif
+ # else
+ if (opa->opcodes[i].op2.jmp_offset != 0) {
+ # endif
+@@ -264,9 +268,9 @@ void vld_branch_info_dump(zend_op_array *opa, vld_branch_info *branch_info)
+ for (i = 0; i < branch_info->starts->size; i++) {
+ if (vld_set_in(branch_info->starts, i)) {
+ fprintf(
+- VLD_G(path_dump_file),
+- "\t\"%s_%d\" [ label = \"{ op #%d-%d | line %d-%d }\" ];\n",
+- fname, i, i,
++ VLD_G(path_dump_file),
++ "\t\"%s_%d\" [ label = \"{ op #%d-%d | line %d-%d }\" ];\n",
++ fname, i, i,
+ branch_info->branches[i].end_op,
+ branch_info->branches[i].start_lineno,
+ branch_info->branches[i].end_lineno
+--
+2.45.2
+
+From 298cea2f3880cdc775fddbdb4fcb334e1f19bfc5 Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Fri, 16 Dec 2022 10:27:40 +0000
+Subject: [PATCH 2/5] Fixed showing the JMP for the 'default' (or error) case
+ in MATCH instructions
+
+---
+ srm_oparray.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/srm_oparray.c b/srm_oparray.c
+index 9fc75d4..54661c3 100644
+--- a/srm_oparray.c
++++ b/srm_oparray.c
+@@ -341,7 +341,7 @@ static const op_usage opcodes[] = {
+ # if PHP_VERSION_ID >= 70400
+ /* 194 */ { "ARRAY_KEY_EXISTS", ALL_USED },
+ # if PHP_VERSION_ID >= 80000
+- /* 195 */ { "MATCH", ALL_USED | OP2_JMP_ARRAY },
++ /* 195 */ { "MATCH", ALL_USED | OP2_JMP_ARRAY | EXT_VAL_JMP_REL },
+ /* 196 */ { "CASE_STRICT", ALL_USED },
+ /* 197 */ { "MATCH_ERROR", ALL_USED },
+ /* 198 */ { "JMP_NULL", ALL_USED },
+--
+2.45.2
+
+From 7d25f1e5949935aa153b37d6bdaf19cf8079772a Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Tue, 28 May 2024 15:09:58 +0100
+Subject: [PATCH 3/5] RECV uses OP2_OPNUM too
+
+---
+ srm_oparray.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/srm_oparray.c b/srm_oparray.c
+index 54661c3..1df6f06 100644
+--- a/srm_oparray.c
++++ b/srm_oparray.c
+@@ -145,7 +145,7 @@ static const op_usage opcodes[] = {
+ /* 60 */ { "DO_FCALL", SPECIAL },
+ /* 61 */ { "INIT_FCALL", ALL_USED },
+ /* 62 */ { "RETURN", OP1_USED },
+- /* 63 */ { "RECV", RES_USED | OP1_USED },
++ /* 63 */ { "RECV", RES_USED | OP1_USED | OP2_OPNUM },
+ /* 64 */ { "RECV_INIT", ALL_USED },
+ /* 65 */ { "SEND_VAL", OP1_USED },
+ /* 66 */ { "SEND_VAR_EX", ALL_USED },
+@@ -649,6 +649,9 @@ static unsigned int vld_get_special_flags(const zend_op *op, unsigned int base_a
+ }
+ #endif
+ break;
++ case ZEND_RECV:
++ flags = OP1_USED|OP2_USED|OP2_OPNUM;
++ break;
+ }
+ return flags;
+ }
+--
+2.45.2
+
+From d7abb0c5ebda8277cda4be37a92d55e29ab5b503 Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Tue, 28 May 2024 15:11:24 +0100
+Subject: [PATCH 4/5] PHP_CHECK_GCC_ARG is now AX_CHECK_COMPILE_FLAG
+
+---
+ config.m4 | 72 +++++++++++++++++++++++++++----------------------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/config.m4 b/config.m4
+index 54b914d..18cfa7d 100644
+--- a/config.m4
++++ b/config.m4
+@@ -20,42 +20,42 @@ if test "$PHP_VLD" != "no"; then
+ CPPFLAGS=$old_CPPFLAGS
+
+ if test "$PHP_VLD_DEV" = "yes"; then
+- PHP_CHECK_GCC_ARG(-Wbool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wbool-conversion")
+- PHP_CHECK_GCC_ARG(-Wdeclaration-after-statement, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdeclaration-after-statement")
+- PHP_CHECK_GCC_ARG(-Wdiscarded-qualifiers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdiscarded-qualifiers")
+- PHP_CHECK_GCC_ARG(-Wduplicate-enum, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wduplicate-enum")
+- PHP_CHECK_GCC_ARG(-Wempty-body, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wempty-body")
+- PHP_CHECK_GCC_ARG(-Wenum-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wenum-compare")
+- PHP_CHECK_GCC_ARG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror")
+- PHP_CHECK_GCC_ARG(-Wextra, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wextra")
+- PHP_CHECK_GCC_ARG(-Wformat-nonliteral, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-nonliteral")
+- PHP_CHECK_GCC_ARG(-Wformat-security, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-security")
+- PHP_CHECK_GCC_ARG(-Wheader-guard, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wheader-guard")
+- PHP_CHECK_GCC_ARG(-Wincompatible-pointer-types-discards-qualifiers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wincompatible-pointer-types-discards-qualifiers")
+- PHP_CHECK_GCC_ARG(-Wimplicit-fallthrough, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wimplicit-fallthrough")
+- PHP_CHECK_GCC_ARG(-Winit-self, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Winit-self")
+- PHP_CHECK_GCC_ARG(-Wlogical-not-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-not-parentheses")
+- PHP_CHECK_GCC_ARG(-Wlogical-op, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op")
+- PHP_CHECK_GCC_ARG(-Wlogical-op-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op-parentheses")
+- PHP_CHECK_GCC_ARG(-Wloop-analysis, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wloop-analysis")
+- PHP_CHECK_GCC_ARG(-Wmaybe-uninitialized, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmaybe-uninitialized")
+- PHP_CHECK_GCC_ARG(-Wmissing-format-attribute, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmissing-format-attribute")
+- PHP_CHECK_GCC_ARG(-Wno-missing-field-initializers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-missing-field-initializers")
+- PHP_CHECK_GCC_ARG(-Wno-sign-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-sign-compare")
+- PHP_CHECK_GCC_ARG(-Wno-unused-but-set-variable, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-but-set-variable")
+- PHP_CHECK_GCC_ARG(-Wno-unused-parameter, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-parameter")
+- PHP_CHECK_GCC_ARG(-Wno-variadic-macros, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-variadic-macros")
+- PHP_CHECK_GCC_ARG(-Wparentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wparentheses")
+- PHP_CHECK_GCC_ARG(-Wpointer-bool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wpointer-bool-conversion")
+- PHP_CHECK_GCC_ARG(-Wsizeof-array-argument, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wsizeof-array-argument")
+- PHP_CHECK_GCC_ARG(-Wstring-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wstring-conversion")
+- PHP_CHECK_GCC_ARG(-Wwrite-strings, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wwrite-strings")
+- PHP_CHECK_GCC_ARG(-fdiagnostics-show-option, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fdiagnostics-show-option")
+- PHP_CHECK_GCC_ARG(-fno-exceptions, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-exceptions")
+- PHP_CHECK_GCC_ARG(-fno-omit-frame-pointer, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-omit-frame-pointer")
+- PHP_CHECK_GCC_ARG(-fno-optimize-sibling-calls, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-optimize-sibling-calls")
+- PHP_CHECK_GCC_ARG(-fsanitize-address, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fsanitize-address")
+- PHP_CHECK_GCC_ARG(-fstack-protector, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fstack-protector")
++ AX_CHECK_COMPILE_FLAG(-Wbool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wbool-conversion")
++ AX_CHECK_COMPILE_FLAG(-Wdeclaration-after-statement, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdeclaration-after-statement")
++ AX_CHECK_COMPILE_FLAG(-Wdiscarded-qualifiers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdiscarded-qualifiers")
++ AX_CHECK_COMPILE_FLAG(-Wduplicate-enum, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wduplicate-enum")
++ AX_CHECK_COMPILE_FLAG(-Wempty-body, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wempty-body")
++ AX_CHECK_COMPILE_FLAG(-Wenum-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wenum-compare")
++ AX_CHECK_COMPILE_FLAG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror")
++ AX_CHECK_COMPILE_FLAG(-Wextra, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wextra")
++ AX_CHECK_COMPILE_FLAG(-Wformat-nonliteral, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-nonliteral")
++ AX_CHECK_COMPILE_FLAG(-Wformat-security, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-security")
++ AX_CHECK_COMPILE_FLAG(-Wheader-guard, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wheader-guard")
++ AX_CHECK_COMPILE_FLAG(-Wincompatible-pointer-types-discards-qualifiers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wincompatible-pointer-types-discards-qualifiers")
++ AX_CHECK_COMPILE_FLAG(-Wimplicit-fallthrough, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wimplicit-fallthrough")
++ AX_CHECK_COMPILE_FLAG(-Winit-self, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Winit-self")
++ AX_CHECK_COMPILE_FLAG(-Wlogical-not-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-not-parentheses")
++ AX_CHECK_COMPILE_FLAG(-Wlogical-op, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op")
++ AX_CHECK_COMPILE_FLAG(-Wlogical-op-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op-parentheses")
++ AX_CHECK_COMPILE_FLAG(-Wloop-analysis, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wloop-analysis")
++ AX_CHECK_COMPILE_FLAG(-Wmaybe-uninitialized, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmaybe-uninitialized")
++ AX_CHECK_COMPILE_FLAG(-Wmissing-format-attribute, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmissing-format-attribute")
++ AX_CHECK_COMPILE_FLAG(-Wno-missing-field-initializers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-missing-field-initializers")
++ AX_CHECK_COMPILE_FLAG(-Wno-sign-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-sign-compare")
++ AX_CHECK_COMPILE_FLAG(-Wno-unused-but-set-variable, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-but-set-variable")
++ AX_CHECK_COMPILE_FLAG(-Wno-unused-parameter, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-parameter")
++ AX_CHECK_COMPILE_FLAG(-Wno-variadic-macros, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-variadic-macros")
++ AX_CHECK_COMPILE_FLAG(-Wparentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wparentheses")
++ AX_CHECK_COMPILE_FLAG(-Wpointer-bool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wpointer-bool-conversion")
++ AX_CHECK_COMPILE_FLAG(-Wsizeof-array-argument, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wsizeof-array-argument")
++ AX_CHECK_COMPILE_FLAG(-Wstring-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wstring-conversion")
++ AX_CHECK_COMPILE_FLAG(-Wwrite-strings, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wwrite-strings")
++ AX_CHECK_COMPILE_FLAG(-fdiagnostics-show-option, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fdiagnostics-show-option")
++ AX_CHECK_COMPILE_FLAG(-fno-exceptions, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-exceptions")
++ AX_CHECK_COMPILE_FLAG(-fno-omit-frame-pointer, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-omit-frame-pointer")
++ AX_CHECK_COMPILE_FLAG(-fno-optimize-sibling-calls, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-optimize-sibling-calls")
++ AX_CHECK_COMPILE_FLAG(-fsanitize-address, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fsanitize-address")
++ AX_CHECK_COMPILE_FLAG(-fstack-protector, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fstack-protector")
+
+ MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS"
+ STD_CFLAGS="-g -O0 -Wall"
+--
+2.45.2
+
+From df1c52c4cb62e5ff31e1b72e3f11df9a45ee567a Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Wed, 26 Jun 2024 16:58:42 +0100
+Subject: [PATCH 5/5] Add support for PHP 8.4 opcodes ZEND_JMP_FRAMELESS and
+ ZEND_FRAMELESS_ICALL_[0-3]
+
+---
+ srm_oparray.c | 29 +++++++++++++++++++++++++++++
+ srm_oparray.h | 2 ++
+ tests/jmp_frameless.inc | 6 ++++++
+ 3 files changed, 37 insertions(+)
+ create mode 100644 tests/jmp_frameless.inc
+
+diff --git a/srm_oparray.c b/srm_oparray.c
+index 1df6f06..3bd6dce 100644
+--- a/srm_oparray.c
++++ b/srm_oparray.c
+@@ -350,6 +350,16 @@ static const op_usage opcodes[] = {
+ /* 200 */ { "FETCH_GLOBALS", ALL_USED },
+ /* 201 */ { "VERIFY_NEVER_TYPE", ALL_USED },
+ /* 202 */ { "ZEND_CALLABLE_CONVERT", ALL_USED },
++# if PHP_VERSION_ID >= 80300
++ /* 203 */ { "ZEND_BIND_INIT_STATIC_OR_JMP", ALL_USED },
++# if PHP_VERSION_ID >= 80400
++ /* 204 */ { "ZEND_FRAMELESS_ICALL_0", ALL_USED | EXT_VAL_FLF },
++ /* 205 */ { "ZEND_FRAMELESS_ICALL_1", ALL_USED | EXT_VAL_FLF },
++ /* 206 */ { "ZEND_FRAMELESS_ICALL_2", ALL_USED | EXT_VAL_FLF },
++ /* 207 */ { "ZEND_FRAMELESS_ICALL_3", ALL_USED | EXT_VAL_FLF },
++ /* 208 */ { "ZEND_JMP_FRAMELESS", ALL_USED | EXT_CACHED_PTR | OP2_OPNUM },
++# endif
++# endif
+ # endif
+ # endif
+ # else
+@@ -814,6 +824,12 @@ void vld_dump_op(int nr, zend_op * op_ptr, unsigned int base_address, int notdea
+ last_lineno = op.lineno;
+ }
+
++#if PHP_VERSION_ID >= 80400
++ if (flags & EXT_VAL_FLF) {
++ fetch_type = (char*) ZEND_FLF_FUNC(&op)->common.function_name->val;
++ }
++#endif
++
+ if (op.opcode >= NUM_KNOWN_OPCODES) {
+ if (VLD_G(format)) {
+ vld_printf(stderr, "%5d %s %c %c %c %c %s <%03d>%-23s %s %-14s ", nr, VLD_G(col_sep), notdead ? ' ' : '*', entry ? 'E' : ' ', start ? '>' : ' ', end ? '>' : ' ', VLD_G(col_sep), op.opcode, VLD_G(col_sep), fetch_type);
+@@ -834,6 +850,11 @@ void vld_dump_op(int nr, zend_op * op_ptr, unsigned int base_address, int notdea
+ }
+ }
+
++#if PHP_VERSION_ID >= 80400
++ if (flags & EXT_CACHED_PTR) {
++ vld_printf(stderr, "s%-3d ", op.extended_value);
++ } else
++#endif
+ if (flags & EXT_VAL) {
+ #if PHP_VERSION_ID >= 70300
+ if (op.opcode == ZEND_CATCH) {
+@@ -1085,6 +1106,14 @@ int vld_find_jumps(zend_op_array *opa, unsigned int position, size_t *jump_count
+ *jump_count = 1;
+ return 1;
+
++#if PHP_VERSION_ID >= 80400
++ } else if (opcode.opcode == ZEND_JMP_FRAMELESS) {
++ jumps[0] = VLD_ZNODE_JMP_LINE(opcode.op2, position, base_address);
++ jumps[1] = position + 1;
++ *jump_count = 2;
++ return 1;
++#endif
++
+ } else if (
+ opcode.opcode == ZEND_GENERATOR_RETURN ||
+ opcode.opcode == ZEND_EXIT ||
+diff --git a/srm_oparray.h b/srm_oparray.h
+index 7cc0803..ee65c25 100644
+--- a/srm_oparray.h
++++ b/srm_oparray.h
+@@ -57,6 +57,8 @@
+ #define EXT_VAL_JMP_ABS 1<<25
+ #define VLD_IS_JMP_ARRAY 1<<26
+ #define VLD_IS_INDEX 1<<27
++#define EXT_VAL_FLF 1<<28
++#define EXT_CACHED_PTR 1<<29
+
+ typedef struct _op_usage {
+ const char *name;
+diff --git a/tests/jmp_frameless.inc b/tests/jmp_frameless.inc
+new file mode 100644
+index 0000000..f693565
+--- /dev/null
++++ b/tests/jmp_frameless.inc
+@@ -0,0 +1,6 @@
++<?php
++namespace Foo {
++
++echo substr("Derick Cool?", 7);
++
++}
+--
+2.45.2
+