From ce8ab5f16a042801b7d1b86e56d71b659bf10d42 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 8 Feb 2025 12:44:58 +0100 Subject: [PATCH 001/503] Fix GH-17736: Assertion failure zend_reference_destroy() The cache slot for FETCH_OBJ_W in function `test` is primed with the class for C. The next call uses a simplexml instance and reuses the same cache slot. simplexml's get_property_ptr handler does not use the cache slot, so the old values remain in the cache slot. When `zend_handle_fetch_obj_flags` is called this is not guarded by a check for the class entry. So we end up using the prop_info from the property C::$a instead of the simplexml property. This patch adds a reset to the cache slots in the property address fetch code and also in the extensions with a non-standard reference handler. This keeps the run time cache consistent and avoids the issue without complicating the fast paths. Closes GH-17739. --- NEWS | 2 ++ Zend/zend_execute.c | 3 +++ ext/date/php_date.c | 1 + ext/dom/php_dom.c | 1 + ext/pdo/pdo_stmt.c | 1 + ext/simplexml/simplexml.c | 2 ++ ext/simplexml/tests/gh17736.phpt | 20 ++++++++++++++++++++ ext/snmp/snmp.c | 1 + ext/spl/spl_array.c | 2 ++ ext/xmlreader/php_xmlreader.c | 2 ++ ext/zip/php_zip.c | 2 ++ 11 files changed, 37 insertions(+) create mode 100644 ext/simplexml/tests/gh17736.phpt diff --git a/NEWS b/NEWS index 0294db412d20e..352dce95e7a42 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.19 +- Treewide: + . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) 27 Feb 2025, PHP 8.3.18RC1 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index dc28578f2c1a3..99da3a4a051f3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3232,6 +3232,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c return; } } + } else if (prop_op_type == IS_CONST) { + /* CE mismatch, make cache slot consistent */ + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; } /* Pointer on property callback is required */ diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 436af32f93536..6f7796eec1250 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4399,6 +4399,7 @@ static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string zend_string_equals_literal(name, "days") || zend_string_equals_literal(name, "invert") ) { /* Fallback to read_property. */ + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; ret = NULL; } else { ret = zend_std_get_property_ptr_ptr(object, name, type, cache_slot); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 7ec107dd712e3..1da53bae64b51 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -303,6 +303,7 @@ static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, in return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; return NULL; } diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 3998b64ab7e13..6aec99026232b 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2495,6 +2495,7 @@ static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name ZEND_IGNORE_VALUE(type); ZEND_IGNORE_VALUE(cache_slot); + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; return NULL; } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 18bfa31271e19..46ec3a2a788ab 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -635,6 +635,8 @@ static zval *sxe_property_get_adr(zend_object *object, zend_string *zname, int f SXE_ITER type; zval member; + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + sxe = php_sxe_fetch_object(object); GET_NODE(sxe, node); if (UNEXPECTED(!node)) { diff --git a/ext/simplexml/tests/gh17736.phpt b/ext/simplexml/tests/gh17736.phpt new file mode 100644 index 0000000000000..78561f6ab0293 --- /dev/null +++ b/ext/simplexml/tests/gh17736.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-17736 (Assertion failure zend_reference_destroy()) +--EXTENSIONS-- +simplexml +--FILE-- +'); +class C { + public int $a = 1; +} +function test($obj) { + $ref =& $obj->a; +} +$obj = new C; +test($obj); +test($o1); +echo "Done\n"; +?> +--EXPECT-- +Done diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index b5bb9f91745c6..02348a5fbca00 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1861,6 +1861,7 @@ static zval *php_snmp_get_property_ptr_ptr(zend_object *object, zend_string *nam return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; return NULL; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 10407bee6a1a8..bd03a8aae0189 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -844,6 +844,8 @@ static zval *spl_array_get_property_ptr_ptr(zend_object *object, zend_string *na if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 && !zend_std_has_property(object, name, ZEND_PROPERTY_EXISTS, NULL)) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + /* If object has offsetGet() overridden, then fallback to read_property, * which will call offsetGet(). */ zval member; diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index ba540692804ef..569058e91a454 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -121,6 +121,8 @@ zval *xmlreader_get_property_ptr_ptr(zend_object *object, zend_string *name, int zval *retval = NULL; xmlreader_prop_handler *hnd = NULL; + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + obj = php_xmlreader_fetch_object(object); if (obj->prop_handler != NULL) { diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 54bdffbecb03b..e28cf688dcff8 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -890,6 +890,8 @@ static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name zval *retval = NULL; zip_prop_handler *hnd = NULL; + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + obj = php_zip_fetch_object(object); if (obj->prop_handler != NULL) { From 1ae2c871d0b69f8cb460eff0c69191a0bbb1f530 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:55:06 +0100 Subject: [PATCH 002/503] Avoid unnecessary string refcounting in ext/date (#17890) --- ext/date/php_date.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 5370377a7fa26..ed89c9d494a6f 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4682,9 +4682,10 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte if (z_arg && Z_TYPE_P(z_arg) == IS_FALSE) { \ (*intobj)->diff->member = TIMELIB_UNSET; \ } else if (z_arg && Z_TYPE_P(z_arg) <= IS_STRING) { \ - zend_string *str = zval_get_string(z_arg); \ + zend_string *tmp_str; \ + zend_string *str = zval_get_tmp_string(z_arg, &tmp_str); \ DATE_A64I((*intobj)->diff->member, ZSTR_VAL(str)); \ - zend_string_release(str); \ + zend_tmp_string_release(tmp_str); \ } else { \ (*intobj)->diff->member = -1LL; \ } \ From 504056888c3b80404d2028364b44b1b301a843ed Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 3 Mar 2025 08:20:48 +0100 Subject: [PATCH 003/503] Fix GH-17938: UAF with zend_test opline observer and magic_quotes_gpc=1 (#17958) --- ext/zend_test/test.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index b2e2756381fdc..a7dd604d89ef3 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -666,6 +666,15 @@ void * zend_test_custom_realloc(void * ptr, size_t len) return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); } +static void zend_test_reset_heap(zend_zend_test_globals *zend_test_globals) +{ + if (zend_test_globals->zend_test_heap) { + free(zend_test_globals->zend_test_heap); + zend_test_globals->zend_test_heap = NULL; + zend_mm_set_heap(zend_test_globals->zend_orig_heap); + } +} + static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) { if (new_value == NULL) { @@ -687,10 +696,8 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) ); ZT_G(zend_orig_heap) = zend_mm_get_heap(); zend_mm_set_heap(ZT_G(zend_test_heap)); - } else if (ZT_G(zend_test_heap)) { - free(ZT_G(zend_test_heap)); - ZT_G(zend_test_heap) = NULL; - zend_mm_set_heap(ZT_G(zend_orig_heap)); + } else { + zend_test_reset_heap(ZEND_MODULE_GLOBALS_BULK(zend_test)); } return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } @@ -1339,6 +1346,7 @@ static PHP_GINIT_FUNCTION(zend_test) static PHP_GSHUTDOWN_FUNCTION(zend_test) { zend_test_observer_gshutdown(zend_test_globals); + zend_test_reset_heap(zend_test_globals); } PHP_MINFO_FUNCTION(zend_test) From 98e050134372b1a4bfd7088ec64f803ed864adda Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 21 Feb 2025 23:30:36 +0100 Subject: [PATCH 004/503] Drop support for `-z` CLI/CGI option This functionality didn't actually work. This was discussed on the mailing list [1] and no one objected. [1] https://externals.io/message/126368 Closes GH-17883. --- NEWS | 1 + UPGRADING | 10 +++++++--- sapi/cgi/cgi_main.c | 6 ------ sapi/cli/php.1.in | 7 ------- sapi/cli/php_cli.c | 5 ----- 5 files changed, 8 insertions(+), 21 deletions(-) diff --git a/NEWS b/NEWS index 675ac03745659..ea08065ce01e3 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - CLI: . Extended --ini to print INI settings changed from the builtin default. (timwolla) + . Drop support for -z CLI/CGI flag. (nielsdos) - COM: . Fixed property access of PHP objects wrapped in variant. (cmb) diff --git a/UPGRADING b/UPGRADING index 6b4f6c335843a..ab034f7f684b1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -362,9 +362,13 @@ PHP 8.5 UPGRADE NOTES ======================================== - Core: - The high resolution timer (`hrtime()`) on macOS now uses the recommended - `clock_gettime_nsec_np(CLOCK_UPTIME_RAW)` API instead of - `mach_absolute_time()`. + . The high resolution timer (`hrtime()`) on macOS now uses the recommended + `clock_gettime_nsec_np(CLOCK_UPTIME_RAW)` API instead of + `mach_absolute_time()`. + +- CLI/CGI: + . The `-z` or `--zend-extension` option has been removed as it was + non-functional. Use `-d zend_extension=` instead. ======================================== 14. Performance Improvements diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 5ede45e766674..392a95d25ea3b 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -158,7 +158,6 @@ static const opt_struct OPTIONS[] = { {'w', 0, "strip"}, {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ {'v', 0, "version"}, - {'z', 1, "zend-extension"}, {'T', 1, "timing"}, {'-', 0, NULL} /* end of args */ }; @@ -1042,7 +1041,6 @@ static void php_cgi_usage(char *argv0) " -s Display colour syntax highlighted source.\n" " -v Version number\n" " -w Display source with stripped comments and whitespace.\n" - " -z Load Zend extension .\n" " -T Measure execution time of script repeated times.\n", prog, prog); } @@ -2383,10 +2381,6 @@ consult the installation file that came with this distribution, or visit \n\ behavior = PHP_MODE_STRIP; break; - case 'z': /* load extension file */ - zend_load_extension(php_optarg); - break; - default: break; } diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in index e8ac382402d23..797ef3242b6a3 100644 --- a/sapi/cli/php.1.in +++ b/sapi/cli/php.1.in @@ -303,13 +303,6 @@ Version number .PD 1 .B \-w Output source with stripped comments and whitespace -.TP -.PD 0 -.B \-\-zend\-extension \fIfile\fP -.TP -.PD 1 -.B \-z \fIfile\fP -Load Zend extension .IR file .TP .IR args.\|.\|. diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index ad2c8d1572715..55246cf96c91d 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -148,7 +148,6 @@ const opt_struct OPTIONS[] = { {'w', 0, "strip"}, {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ {'v', 0, "version"}, - {'z', 1, "zend-extension"}, {10, 1, "rf"}, {10, 1, "rfunction"}, {11, 1, "rc"}, @@ -496,7 +495,6 @@ static void php_cli_usage(char *argv0) " -s Output HTML syntax highlighted source.\n" " -v Version number\n" " -w Output source with stripped comments and whitespace.\n" - " -z Load Zend extension .\n" "\n" " args... Arguments passed to script. Use -- args when first argument\n" " starts with - or script is read from stdin\n" @@ -800,9 +798,6 @@ static int do_cli(int argc, char **argv) /* {{{ */ context.mode = PHP_CLI_MODE_STRIP; break; - case 'z': /* load extension file */ - zend_load_extension(php_optarg); - break; case 'H': hide_argv = true; break; From ff88701b77bd0f3aa738fef495e2e7cc9ad0f5e3 Mon Sep 17 00:00:00 2001 From: Pascal Chevrel Date: Sun, 2 Mar 2025 14:08:28 +0100 Subject: [PATCH 005/503] Fix GH-17956 Internal dev server 404 page is not responsive Add a basic viewport html meta tag with responsive mode parameters See: https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag Updated existing tests close GH-17957 --- NEWS | 2 ++ sapi/cli/php_cli_server.c | 2 +- sapi/cli/tests/php_cli_server_013.phpt | 10 +++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index ea08065ce01e3..3cf7c303fcc59 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Extended --ini to print INI settings changed from the builtin default. (timwolla) . Drop support for -z CLI/CGI flag. (nielsdos) + . Fixed GH-17956 - development server 404 page does not adapt to mobiles. + (pascalchevrel) - COM: . Fixed property access of PHP objects wrapped in variant. (cmb) diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 9e8d8d1b8a418..b7e3e5fa1be2a 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -2026,7 +2026,7 @@ static zend_result php_cli_server_send_error_page(php_cli_server *server, php_cl escaped_request_uri = php_escape_html_entities_ex((const unsigned char *) ZSTR_VAL(client->request.request_uri), ZSTR_LEN(client->request.request_uri), 0, ENT_QUOTES, NULL, /* double_encode */ 0, /* quiet */ 0); { - static const char prologue_template[] = "%d %s"; + static const char prologue_template[] = "%d %s"; php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1); if (!chunk) { goto fail; diff --git a/sapi/cli/tests/php_cli_server_013.phpt b/sapi/cli/tests/php_cli_server_013.phpt index fb334206908a1..ab898a402f942 100644 --- a/sapi/cli/tests/php_cli_server_013.phpt +++ b/sapi/cli/tests/php_cli_server_013.phpt @@ -131,7 +131,7 @@ X-Powered-By: PHP/%s Content-Type: text/html; charset=UTF-8 Content-Length: %d -404 Not Found +404 Not Found

Not Found

The requested resource / was not found on this server.

HTTP/1.1 404 Not Found Host: %s @@ -141,7 +141,7 @@ X-Powered-By: PHP/%s Content-Type: text/html; charset=UTF-8 Content-Length: %d -404 Not Found +404 Not Found

Not Found

The requested resource /main/style.css was not found on this server.

HTTP/1.1 404 Not Found Host: %s @@ -161,7 +161,7 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d Allow: GET, HEAD, POST -405 Method Not Allowed +405 Method Not Allowed

Method Not Allowed

Requested method not allowed.

HTTP/1.1 405 Method Not Allowed Host: %s @@ -172,7 +172,7 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d Allow: GET, HEAD, POST -405 Method Not Allowed +405 Method Not Allowed

Method Not Allowed

Requested method not allowed.

HTTP/1.1 405 Method Not Allowed Host: %s @@ -183,5 +183,5 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d Allow: GET, HEAD, POST -405 Method Not Allowed +405 Method Not Allowed

Method Not Allowed

Requested method not allowed.

From 4694c3e9977e53799870c998991e205056dba4f8 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Mon, 3 Mar 2025 10:04:02 -0400 Subject: [PATCH 006/503] Attempt at ppc64 CI (#17945) This assumes gentoo (which has best ppc64be support of mainstream distributions). (Rebased onto the new workflow_call approach) --- .github/actions/configure-gentoo/action.yml | 81 +++++++++++++++++++++ .github/actions/test-gentoo/action.yml | 34 +++++++++ .github/workflows/nightly.yml | 46 ++++++++++++ .github/workflows/root.yml | 1 + 4 files changed, 162 insertions(+) create mode 100644 .github/actions/configure-gentoo/action.yml create mode 100644 .github/actions/test-gentoo/action.yml diff --git a/.github/actions/configure-gentoo/action.yml b/.github/actions/configure-gentoo/action.yml new file mode 100644 index 0000000000000..e1ae914681fb0 --- /dev/null +++ b/.github/actions/configure-gentoo/action.yml @@ -0,0 +1,81 @@ +name: ./configure +inputs: + configurationParameters: + default: '' + required: false + skipSlow: + default: false + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + ./buildconf --force + ./configure \ + --enable-option-checking=fatal \ + --prefix=/usr \ + --with-libdir=lib64 \ + --enable-phpdbg \ + --enable-fpm \ + --with-pdo-mysql=mysqlnd \ + --with-mysqli=mysqlnd \ + ${{ inputs.skipSlow == 'false' && '--with-pgsql' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-pdo-pgsql' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-pdo-sqlite' || '' }} \ + --enable-intl \ + --without-pear \ + --enable-gd \ + --with-jpeg \ + --with-webp \ + --with-freetype \ + --with-xpm \ + --enable-exif \ + --with-zip \ + --with-zlib \ + --enable-soap \ + --enable-xmlreader \ + --with-xsl \ + ${{ inputs.skipSlow == 'false' && '--with-tidy' || '' }} \ + --enable-sysvsem \ + --enable-sysvshm \ + --enable-shmop \ + --enable-pcntl \ + --with-readline \ + --enable-mbstring \ + --with-iconv \ + --with-curl \ + --with-gettext \ + --enable-sockets \ + --with-bz2 \ + --with-openssl \ + --with-gmp \ + --enable-bcmath \ + --enable-calendar \ + --enable-ftp \ + ${{ inputs.skipSlow == 'false' && '--with-enchant=/usr' || '' }} \ + --enable-sysvmsg \ + --with-ffi \ + --enable-zend-test \ + ${{ inputs.skipSlow == 'false' && '--enable-dl-test=shared' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-ldap' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-ldap-sasl' || '' }} \ + --with-password-argon2 \ + --with-mhash \ + --with-sodium \ + --enable-dba \ + --with-cdb \ + --enable-flatfile \ + --enable-inifile \ + --with-tcadb \ + --with-lmdb \ + --with-qdbm \ + ${{ inputs.skipSlow == 'false' && '--with-snmp' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-unixODBC' || '' }} \ + ${{ inputs.skipSlow == 'false' && '--with-pdo-odbc=unixODBC,/usr' || '' }} \ + --with-config-file-path=/etc \ + --with-config-file-scan-dir=/etc/php.d \ + ${{ inputs.skipSlow == 'false' && '--with-pdo-dblib' || '' }} \ + --enable-werror \ + ${{ inputs.configurationParameters }} || cat config.log diff --git a/.github/actions/test-gentoo/action.yml b/.github/actions/test-gentoo/action.yml new file mode 100644 index 0000000000000..ec9fb0b70c6a3 --- /dev/null +++ b/.github/actions/test-gentoo/action.yml @@ -0,0 +1,34 @@ +name: Test +inputs: + runTestsParameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + # XXX: Set up other database tests? + # XXX: These tests are not running containerized + export MYSQL_TEST_USER=ci + export MYSQL_TEST_PASSWD=ci + if [[ -z "$PDO_MYSQL_TEST_DSN" ]]; then + export PDO_MYSQL_TEST_DSN="mysql:host=localhost;dbname=test" + fi + export PDO_MYSQL_TEST_USER=ci + export PDO_MYSQL_TEST_PASS=ci + export PGSQL_TEST_CONNSTR="host=localhost dbname=test port=5432 user=ci password=ci" + if [[ -z "$PDO_PGSQL_TEST_DSN" ]]; then + export PDO_PGSQL_TEST_DSN="pgsql:host=localhost port=5432 dbname=test user=ci password=ci" + fi + # Slow tests criteron is doubled because this runner isn't as fast as others + export SKIP_IO_CAPTURE_TESTS=1 + export STACK_LIMIT_DEFAULTS_CHECK=1 + sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ + -j$(nproc) \ + -g FAIL,BORK,LEAK,XLEAK \ + --no-progress \ + --show-diff \ + --show-slow 2000 \ + --set-timeout 120 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2377286ca830c..7993c1b6e3586 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -17,6 +17,9 @@ on: run_alpine: required: true type: boolean + run_linux_ppc64: + required: true + type: boolean run_macos_arm64: required: true type: boolean @@ -35,6 +38,49 @@ on: permissions: contents: read jobs: + LINUX_PPC64: + if: inputs.run_linux_ppc64 + name: LINUX_PPC64_ASAN_UBSAN_DEBUG_ZTS + # This runs on a self-hosted runner; see https://wiki.php.net/systems/ci + runs-on: [self-hosted, gentoo, ppc64] + steps: + - name: git checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + - name: System info + run: | + echo "::group::Show host CPU info" + lscpu + echo "::endgroup::" + echo "::group::Show installed packages" + cat /var/lib/portage/world + echo "::endgroup::" + - name: ./configure + uses: ./.github/actions/configure-gentoo + with: + configurationParameters: >- + CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" + LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" + CC=clang-17 + CXX=clang++-17 + --enable-debug + --enable-zts + skipSlow: false # FIXME: This should likely include slow extensions + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + # Skip an install action for now + - name: Tests + uses: ./.github/actions/test-gentoo + # There is no PPC JIT, so rip this out + with: + runTestsParameters: >- + --asan -x + - name: Notify Slack + if: failure() + uses: ./.github/actions/notify-slack + with: + token: ${{ secrets.ACTION_MONITORING_SLACK }} ALPINE: if: inputs.run_alpine name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 5cdd70489343f..25b7a6baadef7 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -53,6 +53,7 @@ jobs: community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} + run_linux_ppc64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} ubuntu_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') From 11876f92fdc3cedf7efab9d9ae0c7d5641db8f00 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:32:58 +0000 Subject: [PATCH 007/503] main: Add a custom Fast ZPP specifier for php_streams --- main/php_streams.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/main/php_streams.h b/main/php_streams.h index 33b14ff4eb3df..80cb96951ee14 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -286,6 +286,35 @@ END_EXTERN_C() #define php_stream_from_zval_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2_ex((pzval), "stream", php_file_le_stream(), php_file_le_pstream()) BEGIN_EXTERN_C() + +static zend_always_inline bool php_stream_zend_parse_arg_into_stream(zval *arg, php_stream **destination_stream_ptr, bool check_null) +{ + if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) { + *destination_stream_ptr = (php_stream*)zend_fetch_resource2(Z_RES_P(arg), "stream", php_file_le_stream(), php_file_le_pstream()); + if (UNEXPECTED(*destination_stream_ptr == NULL)) { + return false; + } + } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + *destination_stream_ptr = NULL; + } else { + return false; + } + return true; +} + +#define PHP_Z_PARAM_STREAM_EX(destination_stream_ptr, check_null) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (UNEXPECTED(!php_stream_zend_parse_arg_into_stream(_arg, &destination_stream_ptr, check_null))) { \ + _error_code = ZPP_ERROR_FAILURE; \ + if (!EG(exception)) { \ + _expected_type = check_null ? Z_EXPECTED_RESOURCE_OR_NULL : Z_EXPECTED_RESOURCE; \ + _error_code = ZPP_ERROR_WRONG_ARG; \ + } \ + break; \ + } +#define PHP_Z_PARAM_STREAM(dest) PHP_Z_PARAM_STREAM_EX(dest, false) +#define PHP_Z_PARAM_STREAM_OR_NULL(dest) PHP_Z_PARAM_STREAM_EX(dest, true) + PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed); #define php_stream_free_enclosed(stream_enclosed, close_options) _php_stream_free_enclosed((stream_enclosed), (close_options)) PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options); From 8787fa2a368c5d8e2f6f1ea3e5b2316fc6ca67cc Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:33:40 +0000 Subject: [PATCH 008/503] ext/standard: Use new php_streams fast ZPP specifier for file functions Fix a corresponding test --- ext/standard/file.c | 101 ++++++---------------------- ext/standard/tests/file/fwrite.phpt | 14 +++- 2 files changed, 32 insertions(+), 83 deletions(-) diff --git a/ext/standard/file.c b/ext/standard/file.c index 01f49640e4af6..908aee85a2e74 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -102,10 +102,6 @@ php_file_globals file_globals; /* }}} */ -#define PHP_STREAM_FROM_ZVAL(stream, arg) \ - ZEND_ASSERT(Z_TYPE_P(arg) == IS_RESOURCE); \ - php_stream_from_res(stream, Z_RES_P(arg)); - /* {{{ ZTS-stuff / Globals / Prototypes */ /* sharing globals is *evil* */ @@ -215,19 +211,17 @@ PHPAPI void php_flock_common(php_stream *stream, zend_long operation, /* {{{ Portable file locking */ PHP_FUNCTION(flock) { - zval *res, *wouldblock = NULL; + zval *wouldblock = NULL; php_stream *stream; zend_long operation = 0; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(operation) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(wouldblock) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - php_flock_common(stream, operation, 2, wouldblock, return_value); } /* }}} */ @@ -756,15 +750,12 @@ PHP_FUNCTION(fopen) /* {{{ Close an open file pointer */ PHPAPI PHP_FUNCTION(fclose) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) { php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " is not a valid stream resource", stream->res->handle); RETURN_FALSE; @@ -836,15 +827,12 @@ PHP_FUNCTION(popen) /* {{{ Close a file pointer opened by popen() */ PHP_FUNCTION(pclose) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - FG(pclose_wait) = 1; zend_list_close(stream->res); FG(pclose_wait) = 0; @@ -855,15 +843,12 @@ PHP_FUNCTION(pclose) /* {{{ Test for end-of-file on a file pointer */ PHPAPI PHP_FUNCTION(feof) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (php_stream_eof(stream)) { RETURN_TRUE; } else { @@ -875,7 +860,6 @@ PHPAPI PHP_FUNCTION(feof) /* {{{ Get a line from file pointer */ PHPAPI PHP_FUNCTION(fgets) { - zval *res; zend_long len = 1024; bool len_is_null = 1; char *buf = NULL; @@ -884,13 +868,11 @@ PHPAPI PHP_FUNCTION(fgets) php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(len, len_is_null) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (len_is_null) { /* ask streams to give us a buffer of an appropriate size */ buf = php_stream_get_line(stream, NULL, 0, &line_len); @@ -926,15 +908,12 @@ PHPAPI PHP_FUNCTION(fgets) /* {{{ Get a character from file pointer */ PHPAPI PHP_FUNCTION(fgetc) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - int result = php_stream_getc(stream); if (result == EOF) { @@ -989,7 +968,6 @@ PHP_FUNCTION(fscanf) /* {{{ Binary-safe file write */ PHPAPI PHP_FUNCTION(fwrite) { - zval *res; char *input; size_t inputlen; ssize_t ret; @@ -999,7 +977,7 @@ PHPAPI PHP_FUNCTION(fwrite) php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(input, inputlen) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) @@ -1017,8 +995,6 @@ PHPAPI PHP_FUNCTION(fwrite) RETURN_LONG(0); } - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_write(stream, input, num_bytes); if (ret < 0) { RETURN_FALSE; @@ -1031,16 +1007,13 @@ PHPAPI PHP_FUNCTION(fwrite) /* {{{ Flushes output */ PHPAPI PHP_FUNCTION(fflush) { - zval *res; int ret; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_flush(stream); if (ret) { RETURN_FALSE; @@ -1052,15 +1025,12 @@ PHPAPI PHP_FUNCTION(fflush) /* {{{ Rewind the position of a file pointer */ PHPAPI PHP_FUNCTION(rewind) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (-1 == php_stream_rewind(stream)) { RETURN_FALSE; } @@ -1071,16 +1041,13 @@ PHPAPI PHP_FUNCTION(rewind) /* {{{ Get file pointer's read/write position */ PHPAPI PHP_FUNCTION(ftell) { - zval *res; zend_long ret; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_tell(stream); if (ret == -1) { RETURN_FALSE; @@ -1092,19 +1059,16 @@ PHPAPI PHP_FUNCTION(ftell) /* {{{ Seek on a file pointer */ PHPAPI PHP_FUNCTION(fseek) { - zval *res; zend_long offset, whence = SEEK_SET; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL Z_PARAM_LONG(whence) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - RETURN_LONG(php_stream_seek(stream, offset, (int) whence)); } /* }}} */ @@ -1215,16 +1179,13 @@ PHP_FUNCTION(umask) /* {{{ Output all remaining data from a file pointer */ PHPAPI PHP_FUNCTION(fpassthru) { - zval *res; size_t size; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - size = php_stream_passthru(stream); RETURN_LONG(size); } @@ -1303,15 +1264,12 @@ PHP_FUNCTION(unlink) PHP_FUNCTION(fsync) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (!php_stream_sync_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't fsync this stream!"); RETURN_FALSE; @@ -1322,15 +1280,12 @@ PHP_FUNCTION(fsync) PHP_FUNCTION(fdatasync) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (!php_stream_sync_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't fsync this stream!"); RETURN_FALSE; @@ -1342,12 +1297,11 @@ PHP_FUNCTION(fdatasync) /* {{{ Truncate file to 'size' length */ PHP_FUNCTION(ftruncate) { - zval *fp; zend_long size; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(size) ZEND_PARSE_PARAMETERS_END(); @@ -1356,8 +1310,6 @@ PHP_FUNCTION(ftruncate) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fp); - if (!php_stream_truncate_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't truncate this stream!"); RETURN_FALSE; @@ -1441,15 +1393,12 @@ PHPAPI void php_fstat(php_stream *stream, zval *return_value) /* {{{ Stat() on a filehandle */ PHP_FUNCTION(fstat) { - zval *fp; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, fp); - php_fstat(stream, return_value); } /* }}} */ @@ -1588,18 +1537,15 @@ PHPAPI zend_result php_copy_file_ctx(const char *src, const char *dest, int src_ /* {{{ Binary-safe file read */ PHPAPI PHP_FUNCTION(fread) { - zval *res; zend_long len; php_stream *stream; zend_string *str; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(len) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (len <= 0) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); @@ -1683,7 +1629,7 @@ PHP_FUNCTION(fputcsv) char delimiter = ','; /* allow this to be set as parameter */ char enclosure = '"'; /* allow this to be set as parameter */ php_stream *stream; - zval *fp = NULL, *fields = NULL; + zval *fields = NULL; ssize_t ret; char *delimiter_str = NULL, *enclosure_str = NULL; zend_string *escape_str = NULL; @@ -1691,7 +1637,7 @@ PHP_FUNCTION(fputcsv) zend_string *eol_str = NULL; ZEND_PARSE_PARAMETERS_START(2, 6) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_ARRAY(fields) Z_PARAM_OPTIONAL Z_PARAM_STRING(delimiter_str, delimiter_str_len) @@ -1725,8 +1671,6 @@ PHP_FUNCTION(fputcsv) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fp); - ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char, eol_str); if (ret < 0) { RETURN_FALSE; @@ -1811,7 +1755,6 @@ PHP_FUNCTION(fgetcsv) char *buf; php_stream *stream; - zval *fd; bool len_is_null = 1; char *delimiter_str = NULL; size_t delimiter_str_len = 0; @@ -1820,7 +1763,7 @@ PHP_FUNCTION(fgetcsv) zend_string *escape_str = NULL; ZEND_PARSE_PARAMETERS_START(1, 5) - Z_PARAM_RESOURCE(fd) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(len, len_is_null) Z_PARAM_STRING(delimiter_str, delimiter_str_len) @@ -1861,8 +1804,6 @@ PHP_FUNCTION(fgetcsv) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fd); - if (len < 0) { if ((buf = php_stream_get_line(stream, NULL, 0, &buf_len)) == NULL) { RETURN_FALSE; diff --git a/ext/standard/tests/file/fwrite.phpt b/ext/standard/tests/file/fwrite.phpt index 90e158d048a6c..1494ea7a0f5e8 100644 --- a/ext/standard/tests/file/fwrite.phpt +++ b/ext/standard/tests/file/fwrite.phpt @@ -17,13 +17,21 @@ var_dump(fwrite($fp, "data", -1)); var_dump(fwrite($fp, "data", 100000)); fclose($fp); -var_dump(fwrite($fp, "data", -1)); +try { + var_dump(fwrite($fp, "data", -1)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} var_dump(file_get_contents($filename)); -@unlink($filename); echo "Done\n"; ?> +--CLEAN-- + --EXPECTF-- int(0) @@ -31,6 +39,6 @@ Notice: fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor in %s bool(false) int(0) int(4) -int(0) +TypeError: fwrite(): supplied resource is not a valid stream resource string(4) "data" Done From f3857dd613c9ad030c691466762ffea6bb7349c1 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:43:17 +0000 Subject: [PATCH 009/503] ext/standard: Use new php_streams fast ZPP specifier for stream functions --- ext/standard/streamsfuncs.c | 104 ++++++++---------------------------- 1 file changed, 22 insertions(+), 82 deletions(-) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 4f9a7106c01c1..818a645086b05 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -265,11 +265,10 @@ PHP_FUNCTION(stream_socket_accept) php_timeout_ull conv; struct timeval tv; php_stream *stream = NULL, *clistream = NULL; - zval *zstream; zend_string *errstr = NULL; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_DOUBLE_OR_NULL(timeout, timeout_is_null) Z_PARAM_ZVAL(zpeername) @@ -282,8 +281,6 @@ PHP_FUNCTION(stream_socket_accept) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - /* prepare the timeout value for use */ struct timeval *tv_pointer; if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { @@ -328,17 +325,14 @@ PHP_FUNCTION(stream_socket_accept) PHP_FUNCTION(stream_socket_get_name) { php_stream *stream; - zval *zstream; bool want_peer; zend_string *name = NULL; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(want_peer) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (0 != php_stream_xport_get_name(stream, want_peer, &name, NULL, NULL @@ -359,7 +353,6 @@ PHP_FUNCTION(stream_socket_get_name) PHP_FUNCTION(stream_socket_sendto) { php_stream *stream; - zval *zstream; zend_long flags = 0; char *data, *target_addr = NULL; size_t datalen, target_addr_len = 0; @@ -367,13 +360,12 @@ PHP_FUNCTION(stream_socket_sendto) socklen_t sl = 0; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(data, datalen) Z_PARAM_OPTIONAL Z_PARAM_LONG(flags) Z_PARAM_STRING(target_addr, target_addr_len) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); if (target_addr_len) { /* parse the address */ @@ -391,7 +383,7 @@ PHP_FUNCTION(stream_socket_sendto) PHP_FUNCTION(stream_socket_recvfrom) { php_stream *stream; - zval *zstream, *zremote = NULL; + zval *zremote = NULL; zend_string *remote_addr = NULL; zend_long to_read = 0; zend_string *read_buf; @@ -399,15 +391,13 @@ PHP_FUNCTION(stream_socket_recvfrom) int recvd; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(to_read) Z_PARAM_OPTIONAL Z_PARAM_LONG(flags) Z_PARAM_ZVAL(zremote) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (zremote) { ZEND_TRY_ASSIGN_REF_NULL(zremote); } @@ -441,13 +431,12 @@ PHP_FUNCTION(stream_socket_recvfrom) PHP_FUNCTION(stream_get_contents) { php_stream *stream; - zval *zsrc; zend_long maxlen, desiredpos = -1L; bool maxlen_is_null = 1; zend_string *contents; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) Z_PARAM_LONG(desiredpos) @@ -460,8 +449,6 @@ PHP_FUNCTION(stream_get_contents) RETURN_THROWS(); } - php_stream_from_zval(stream, zsrc); - if (desiredpos >= 0) { int seek_res = 0; zend_off_t position; @@ -494,15 +481,14 @@ PHP_FUNCTION(stream_get_contents) PHP_FUNCTION(stream_copy_to_stream) { php_stream *src, *dest; - zval *zsrc, *zdest; zend_long maxlen, pos = 0; bool maxlen_is_null = 1; size_t len; int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zsrc) - Z_PARAM_RESOURCE(zdest) + PHP_Z_PARAM_STREAM(src) + PHP_Z_PARAM_STREAM(dest) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) Z_PARAM_LONG(pos) @@ -512,9 +498,6 @@ PHP_FUNCTION(stream_copy_to_stream) maxlen = PHP_STREAM_COPY_ALL; } - php_stream_from_zval(src, zsrc); - php_stream_from_zval(dest, zdest); - if (pos > 0 && php_stream_seek(src, pos, SEEK_SET) < 0) { php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", pos); RETURN_FALSE; @@ -532,15 +515,12 @@ PHP_FUNCTION(stream_copy_to_stream) /* {{{ Retrieves header/meta data from streams/file pointers */ PHP_FUNCTION(stream_get_meta_data) { - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - array_init(return_value); if (!php_stream_populate_meta_data(stream, return_value)) { @@ -1235,7 +1215,6 @@ PHP_FUNCTION(stream_context_create) /* {{{ streams filter functions */ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) { - zval *zstream; php_stream *stream; char *filtername; size_t filternamelen; @@ -1245,15 +1224,13 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(filtername, filternamelen) Z_PARAM_OPTIONAL Z_PARAM_LONG(read_write) Z_PARAM_ZVAL(filterparams) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if ((read_write & PHP_STREAM_FILTER_ALL) == 0) { /* Chain not specified. * Examine stream->mode to determine which filters are needed @@ -1358,12 +1335,11 @@ PHP_FUNCTION(stream_get_line) char *str = NULL; size_t str_len = 0; zend_long max_length; - zval *zstream; zend_string *buf; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(max_length) Z_PARAM_OPTIONAL Z_PARAM_STRING(str, str_len) @@ -1377,8 +1353,6 @@ PHP_FUNCTION(stream_get_line) max_length = PHP_SOCK_CHUNK_SIZE; } - php_stream_from_zval(stream, zstream); - if ((buf = php_stream_get_record(stream, max_length, str, str_len))) { RETURN_STR(buf); } else { @@ -1391,17 +1365,14 @@ PHP_FUNCTION(stream_get_line) /* {{{ Set blocking/non-blocking mode on a socket or stream */ PHP_FUNCTION(stream_set_blocking) { - zval *zstream; bool block; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(block) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block, NULL) == -1) { RETURN_FALSE; } @@ -1415,21 +1386,18 @@ PHP_FUNCTION(stream_set_blocking) #if defined(HAVE_SYS_TIME_H) || defined(PHP_WIN32) PHP_FUNCTION(stream_set_timeout) { - zval *socket; zend_long seconds, microseconds = 0; struct timeval t; php_stream *stream; int argc = ZEND_NUM_ARGS(); ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(socket) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(seconds) Z_PARAM_OPTIONAL Z_PARAM_LONG(microseconds) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, socket); - #ifdef PHP_WIN32 t.tv_sec = (long)seconds; @@ -1462,19 +1430,16 @@ PHP_FUNCTION(stream_set_timeout) /* {{{ Set file write buffer */ PHP_FUNCTION(stream_set_write_buffer) { - zval *arg1; int ret; zend_long arg2; size_t buff; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - buff = arg2; /* if buff is 0 then set to non-buffered */ @@ -1493,11 +1458,10 @@ PHP_FUNCTION(stream_set_chunk_size) { int ret; zend_long csize; - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(csize) ZEND_PARSE_PARAMETERS_END(); @@ -1514,8 +1478,6 @@ PHP_FUNCTION(stream_set_chunk_size) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_SET_CHUNK_SIZE, (int)csize, NULL); RETURN_LONG(ret > 0 ? (zend_long)ret : (zend_long)EOF); @@ -1525,19 +1487,16 @@ PHP_FUNCTION(stream_set_chunk_size) /* {{{ Set file read buffer */ PHP_FUNCTION(stream_set_read_buffer) { - zval *arg1; int ret; zend_long arg2; size_t buff; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - buff = arg2; /* if buff is 0 then set to non-buffered */ @@ -1555,21 +1514,18 @@ PHP_FUNCTION(stream_set_read_buffer) PHP_FUNCTION(stream_socket_enable_crypto) { zend_long cryptokind = 0; - zval *zstream, *zsessstream = NULL; php_stream *stream, *sessstream = NULL; bool enable, cryptokindnull = 1; int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(enable) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(cryptokind, cryptokindnull) - Z_PARAM_RESOURCE_OR_NULL(zsessstream) + PHP_Z_PARAM_STREAM_OR_NULL(sessstream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (enable) { if (cryptokindnull) { zval *val; @@ -1582,10 +1538,6 @@ PHP_FUNCTION(stream_socket_enable_crypto) cryptokind = Z_LVAL_P(val); } - if (zsessstream) { - php_stream_from_zval(sessstream, zsessstream); - } - if (php_stream_xport_crypto_setup(stream, cryptokind, sessstream) < 0) { RETURN_FALSE; } @@ -1658,14 +1610,11 @@ PHP_FUNCTION(stream_is_local) PHP_FUNCTION(stream_supports_lock) { php_stream *stream; - zval *zsrc; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - if (!php_stream_supports_lock(stream)) { RETURN_FALSE; } @@ -1676,16 +1625,13 @@ PHP_FUNCTION(stream_supports_lock) /* {{{ Check if a stream is a TTY. */ PHP_FUNCTION(stream_isatty) { - zval *zsrc; php_stream *stream; php_socket_t fileno; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - /* get the fd. * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag when casting. * It is only used here so that the buffered data warning is not displayed. @@ -1718,19 +1664,16 @@ PHP_FUNCTION(stream_isatty) */ PHP_FUNCTION(sapi_windows_vt100_support) { - zval *zsrc; php_stream *stream; bool enable, enable_is_null = 1; zend_long fileno; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_BOOL_OR_NULL(enable, enable_is_null) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - /* get the fd. * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag when casting. * It is only used here so that the buffered data warning is not displayed. @@ -1785,11 +1728,10 @@ PHP_FUNCTION(sapi_windows_vt100_support) PHP_FUNCTION(stream_socket_shutdown) { zend_long how; - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(how) ZEND_PARSE_PARAMETERS_END(); @@ -1800,8 +1742,6 @@ PHP_FUNCTION(stream_socket_shutdown) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how) == 0); } /* }}} */ From da1fde28f3ef2ae4cb07587203f7363229370d56 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:57:44 +0000 Subject: [PATCH 010/503] ext/standard: Use new php_streams fast ZPP specifier --- ext/standard/formatted_print.c | 14 +++++--------- ext/standard/user_filters.c | 5 ++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index 8d8c09f443c04..9471ad3c7ba23 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -860,18 +860,16 @@ PHP_FUNCTION(fprintf) php_stream *stream; char *format; size_t format_len; - zval *arg1, *args; - int argc; + zval *args = NULL; + int argc = 0; zend_string *result; ZEND_PARSE_PARAMETERS_START(2, -1) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(format, format_len) Z_PARAM_VARIADIC('*', args, argc) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - result = php_formatted_print(format, format_len, args, argc, 2); if (result == NULL) { RETURN_THROWS(); @@ -890,19 +888,17 @@ PHP_FUNCTION(vfprintf) php_stream *stream; char *format; size_t format_len; - zval *arg1, *args; + zval *args; zend_array *array; int argc; zend_string *result; ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(format, format_len) Z_PARAM_ARRAY_HT(array) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - args = php_formatted_print_get_array(array, &argc); result = php_formatted_print(format, format_len, args, argc, -1); diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 2168fbce0af34..88facf1e137f2 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -439,7 +439,7 @@ PHP_FUNCTION(stream_bucket_append) /* {{{ Create a new bucket for use on the current stream */ PHP_FUNCTION(stream_bucket_new) { - zval *zstream, zbucket; + zval zbucket; php_stream *stream; char *buffer; char *pbuffer; @@ -447,11 +447,10 @@ PHP_FUNCTION(stream_bucket_new) php_stream_bucket *bucket; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ZVAL(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(buffer, buffer_len) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); pbuffer = pemalloc(buffer_len, php_stream_is_persistent(stream)); memcpy(pbuffer, buffer, buffer_len); From c9d23c96d6ed75bfa39ad0925d8d3fbe8be1075d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:38:14 +0000 Subject: [PATCH 011/503] ext/ftp: Use new php_streams fast ZPP specifier --- ext/ftp/php_ftp.c | 60 +++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 0336f9e953773..17dc94b728eba 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -566,7 +566,7 @@ PHP_FUNCTION(ftp_systype) /* {{{ Retrieves a file from the FTP server and writes it to an open file */ PHP_FUNCTION(ftp_fget) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; @@ -574,11 +574,16 @@ PHP_FUNCTION(ftp_fget) size_t file_len; zend_long mode=FTPTYPE_IMAGE, resumepos=0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_STRING(file, file_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(resumepos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -610,7 +615,7 @@ PHP_FUNCTION(ftp_fget) /* {{{ Retrieves a file from the FTP server asynchronly and writes it to an open file */ PHP_FUNCTION(ftp_nb_fget) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; @@ -618,11 +623,16 @@ PHP_FUNCTION(ftp_nb_fget) size_t file_len; zend_long mode=FTPTYPE_IMAGE, resumepos=0, ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_STRING(file, file_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(resumepos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -848,7 +858,7 @@ PHP_FUNCTION(ftp_nb_continue) /* {{{ Stores a file from an open file to the FTP server */ PHP_FUNCTION(ftp_fput) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; size_t remote_len; @@ -856,11 +866,16 @@ PHP_FUNCTION(ftp_fput) php_stream *stream; char *remote; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + Z_PARAM_STRING(remote, remote_len) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(startpos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_zval(stream, z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -895,7 +910,7 @@ PHP_FUNCTION(ftp_fput) /* {{{ Stores a file from an open file to the FTP server nbronly */ PHP_FUNCTION(ftp_nb_fput) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; size_t remote_len; @@ -904,11 +919,16 @@ PHP_FUNCTION(ftp_nb_fput) php_stream *stream; char *remote; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + Z_PARAM_STRING(remote, remote_len) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(startpos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ From eb4ccf5758bee0ece1b0a457de87e010bbf61e80 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:52:27 +0000 Subject: [PATCH 012/503] ext/pgsql: Use new php_streams fast ZPP specifier --- ext/pgsql/pgsql.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index b1a1dfb49a7ac..036fc5c0572a1 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -6265,22 +6265,19 @@ PHP_FUNCTION(pg_put_copy_end) PHP_FUNCTION(pg_socket_poll) { - zval *z_socket; php_stream *stream; php_socket_t socket; zend_long read, write; zend_long ts = -1; ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_RESOURCE(z_socket) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(read) Z_PARAM_LONG(write) Z_PARAM_OPTIONAL Z_PARAM_LONG(ts) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, z_socket); - if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void **)&socket, 0)) { zend_argument_type_error(1, "invalid resource socket"); RETURN_THROWS(); From ff40eed32dd81a4fbfa2e48e12540696badc8871 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:54:51 +0000 Subject: [PATCH 013/503] ext/hash: Use new php_streams fast ZPP specifier --- ext/hash/hash.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 5579aeb978e3c..13c345de4dd1c 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -707,18 +707,20 @@ PHP_FUNCTION(hash_update) /* {{{ Pump data into the hashing algorithm from an open stream */ PHP_FUNCTION(hash_update_stream) { - zval *zhash, *zstream; + zend_object *hash_obj; php_hashcontext_object *hash; php_stream *stream = NULL; zend_long length = -1, didread = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Or|l", &zhash, php_hashcontext_ce, &zstream, &length) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_OBJ_OF_CLASS(hash_obj, php_hashcontext_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(length) + ZEND_PARSE_PARAMETERS_END(); - hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); + hash = php_hashcontext_from_object(hash_obj); PHP_HASHCONTEXT_VERIFY(hash); - php_stream_from_zval(stream, zstream); while (length) { char buf[1024]; From 9285559c8cb61e986dd67132683bc6c52b1048f5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:59:55 +0000 Subject: [PATCH 014/503] ext/bz2: Use new php_streams fast ZPP specifier --- ext/bz2/bz2.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index d95a4d5036800..9ed5342a7df8f 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -303,16 +303,15 @@ static PHP_MINFO_FUNCTION(bz2) /* {{{ Reads up to length bytes from a BZip2 stream, or 1024 bytes if length is not specified */ PHP_FUNCTION(bzread) { - zval *bz; zend_long len = 1024; php_stream *stream; zend_string *data; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &bz, &len)) { - RETURN_THROWS(); - } - - php_stream_from_zval(stream, bz); + ZEND_PARSE_PARAMETERS_START(1, 2) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(len) + ZEND_PARSE_PARAMETERS_END(); if (len < 0) { zend_argument_value_error(2, "must be greater than or equal to 0"); @@ -563,17 +562,14 @@ PHP_FUNCTION(bzdecompress) The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) { - zval *bzp; /* BZip2 Resource Pointer */ php_stream *stream; const char *errstr; /* Error string */ int errnum; /* Error number */ struct php_bz2_stream_data_t *self; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &bzp) == FAILURE) { - RETURN_THROWS(); - } - - php_stream_from_zval(stream, bzp); + ZEND_PARSE_PARAMETERS_START(1, 1) + PHP_Z_PARAM_STREAM(stream) + ZEND_PARSE_PARAMETERS_END(); if (!php_stream_is(stream, PHP_STREAM_IS_BZIP2)) { zend_argument_type_error(1, "must be a bz2 stream"); From f016caa312ae83b15979d59d1a1bbd86248bc437 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 3 Mar 2025 23:48:08 +0300 Subject: [PATCH 015/503] Merge IR IR commit: 1a02c4819f210a1f4548b83850ed7cd5c76c13aa --- ext/opcache/jit/ir/ir.c | 36 +++++++++++++---------------- ext/opcache/jit/ir/ir_cfg.c | 22 ++++++++++++++---- ext/opcache/jit/ir/ir_check.c | 12 +++++----- ext/opcache/jit/ir/ir_dump.c | 2 +- ext/opcache/jit/ir/ir_emit.c | 4 ++-- ext/opcache/jit/ir/ir_ra.c | 11 +++++---- ext/opcache/jit/ir/ir_save.c | 2 +- ext/opcache/jit/ir/ir_sccp.c | 14 ++++++++++-- ext/opcache/jit/ir/ir_x86.dasc | 41 ++++++++++++++++++++++++++++++++-- 9 files changed, 100 insertions(+), 44 deletions(-) diff --git a/ext/opcache/jit/ir/ir.c b/ext/opcache/jit/ir/ir.c index a6bb7c993c51b..2721de4a6e006 100644 --- a/ext/opcache/jit/ir/ir.c +++ b/ext/opcache/jit/ir/ir.c @@ -1294,69 +1294,65 @@ void ir_build_def_use_lists(ir_ctx *ctx) void ir_use_list_remove_all(ir_ctx *ctx, ir_ref from, ir_ref ref) { - ir_ref j, n, *p, *q, use; + ir_ref n, *p, *q, use; ir_use_list *use_list; - ir_ref skip = 0; IR_ASSERT(from > 0); use_list = &ctx->use_lists[from]; n = use_list->count; - for (j = 0, p = q = &ctx->use_edges[use_list->refs]; j < n; j++, p++) { + for (p = q = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; - if (use == ref) { - skip++; - } else { + if (use != ref) { if (p != q) { *q = use; } q++; } } - if (skip) { - use_list->count -= skip; + if (p != q) { + use_list->count -= (p - q); do { *q = IR_UNUSED; q++; - } while (--skip); + } while (q != p); } } void ir_use_list_remove_one(ir_ctx *ctx, ir_ref from, ir_ref ref) { - ir_ref j, n, *p; + ir_ref n, *p; ir_use_list *use_list; IR_ASSERT(from > 0); use_list = &ctx->use_lists[from]; n = use_list->count; - j = 0; p = &ctx->use_edges[use_list->refs]; - while (j < n) { + while (n > 0) { if (*p == ref) { use_list->count--; - j++; - while (j < n) { + n--; + while (n > 0) { *p = *(p+1); p++; - j++; + n--; } *p = IR_UNUSED; break; } p++; - j++; + n--; } } void ir_use_list_replace_one(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_ref new_use) { ir_use_list *use_list; - ir_ref i, n, *p; + ir_ref n, *p; IR_ASSERT(ref > 0); use_list = &ctx->use_lists[ref]; n = use_list->count; - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { if (*p == use) { *p = new_use; break; @@ -1367,12 +1363,12 @@ void ir_use_list_replace_one(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_ref new_use void ir_use_list_replace_all(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_ref new_use) { ir_use_list *use_list; - ir_ref i, n, *p; + ir_ref n, *p; IR_ASSERT(ref > 0); use_list = &ctx->use_lists[ref]; n = use_list->count; - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { if (*p == use) { *p = new_use; } diff --git a/ext/opcache/jit/ir/ir_cfg.c b/ext/opcache/jit/ir/ir_cfg.c index 3678867e46c7a..16facae51b1f6 100644 --- a/ext/opcache/jit/ir/ir_cfg.c +++ b/ext/opcache/jit/ir/ir_cfg.c @@ -328,7 +328,7 @@ static void ir_remove_predecessor(ir_ctx *ctx, ir_block *bb, uint32_t from) static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from) { - ir_ref i, j, n, k, *p, use; + ir_ref i, j, n, k, *p, *q, use; ir_insn *use_insn; ir_use_list *use_list; ir_bitset life_inputs; @@ -359,7 +359,7 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from) use_list = &ctx->use_lists[merge]; if (use_list->count > 1) { n++; - for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) { + for (k = use_list->count, p = q = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) { use = *p; use_insn = &ctx->ir_base[use]; if (use_insn->op == IR_PHI) { @@ -379,8 +379,22 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from) for (j = 2; j <= n; j++) { ir_insn_set_op(use_insn, j, IR_UNUSED); } - ir_use_list_remove_all(ctx, merge, use); + continue; + } + + /*compact use list */ + if (p != q){ + *q = use; } + q++; + } + + if (p != q) { + use_list->count -= (p - q); + do { + *q = IR_UNUSED; /* clenu-op the removed tail */ + q++; + } while (p != q); } } } else { @@ -389,7 +403,7 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from) use_list = &ctx->use_lists[merge]; if (use_list->count > 1) { n++; - for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) { + for (k = use_list->count, p = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) { use = *p; use_insn = &ctx->ir_base[use]; if (use_insn->op == IR_PHI) { diff --git a/ext/opcache/jit/ir/ir_check.c b/ext/opcache/jit/ir/ir_check.c index 40a475ae22f99..f12b4776fa1e0 100644 --- a/ext/opcache/jit/ir/ir_check.c +++ b/ext/opcache/jit/ir/ir_check.c @@ -42,11 +42,11 @@ void ir_consistency_check(void) static bool ir_check_use_list(const ir_ctx *ctx, ir_ref from, ir_ref to) { - ir_ref n, j, *p; + ir_ref n, *p; ir_use_list *use_list = &ctx->use_lists[from]; n = use_list->count; - for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { if (*p == to) { return 1; } @@ -304,9 +304,9 @@ bool ir_check(const ir_ctx *ctx) if (ctx->use_lists) { ir_use_list *use_list = &ctx->use_lists[i]; - ir_ref count; + ir_ref count, n = use_list->count; - for (j = 0, p = &ctx->use_edges[use_list->refs]; j < use_list->count; j++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; if (!ir_check_input_list(ctx, i, use)) { fprintf(stderr, "ir_base[%d] is in use list of ir_base[%d]\n", use, i); @@ -347,8 +347,8 @@ bool ir_check(const ir_ctx *ctx) break; default: /* skip data references */ - count = use_list->count; - for (j = 0, p = &ctx->use_edges[use_list->refs]; j < use_list->count; j++, p++) { + count = n = use_list->count; + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; if (!(ir_op_flags[ctx->ir_base[use].op] & IR_OP_FLAG_CONTROL)) { count--; diff --git a/ext/opcache/jit/ir/ir_dump.c b/ext/opcache/jit/ir/ir_dump.c index f9b26c4d2a12a..54fddf50ac066 100644 --- a/ext/opcache/jit/ir/ir_dump.c +++ b/ext/opcache/jit/ir/ir_dump.c @@ -177,7 +177,7 @@ static void ir_dump_dessa_moves(const ir_ctx *ctx, int b, ir_block *bb, FILE *f) use_list = &ctx->use_lists[succ_bb->start]; k = ir_phi_input_number(ctx, succ_bb, b); - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { use_ref = *p; use_insn = &ctx->ir_base[use_ref]; if (use_insn->op == IR_PHI) { diff --git a/ext/opcache/jit/ir/ir_emit.c b/ext/opcache/jit/ir/ir_emit.c index 367dee72963bf..5cf44a51d0f48 100644 --- a/ext/opcache/jit/ir/ir_emit.c +++ b/ext/opcache/jit/ir/ir_emit.c @@ -161,7 +161,7 @@ static ir_reg ir_get_param_reg(const ir_ctx *ctx, ir_ref ref) } #endif - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { use = *p; insn = &ctx->ir_base[use]; if (insn->op == IR_PARAM) { @@ -917,7 +917,7 @@ static void ir_emit_dessa_moves(ir_ctx *ctx, int b, ir_block *bb) copies = alloca(use_list->count * sizeof(ir_dessa_copy)); - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { ir_ref ref = *p; ir_insn *insn = &ctx->ir_base[ref]; diff --git a/ext/opcache/jit/ir/ir_ra.c b/ext/opcache/jit/ir/ir_ra.c index dcc67e0074fa4..0c0e8dec3b47a 100644 --- a/ext/opcache/jit/ir/ir_ra.c +++ b/ext/opcache/jit/ir/ir_ra.c @@ -1901,7 +1901,6 @@ int ir_coalesce(ir_ctx *ctx) qsort(list, count, sizeof(ir_coalesce_block), ir_block_cmp); while (count > 0) { - uint32_t i; count--; b = list[count].b; @@ -1913,7 +1912,7 @@ int ir_coalesce(ir_ctx *ctx) k = ir_phi_input_number(ctx, succ_bb, b); use_list = &ctx->use_lists[succ_bb->start]; n = use_list->count; - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; insn = &ctx->ir_base[use]; if (insn->op == IR_PHI) { @@ -2061,7 +2060,7 @@ int ir_coalesce(ir_ctx *ctx) int ir_compute_dessa_moves(ir_ctx *ctx) { - uint32_t b, i, n; + uint32_t b, n; ir_ref j, k, *p, use; ir_block *bb; ir_use_list *use_list; @@ -2076,7 +2075,7 @@ int ir_compute_dessa_moves(ir_ctx *ctx) if (n > 1) { IR_ASSERT(k == ctx->ir_base[bb->start].inputs_count); k++; - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; insn = &ctx->ir_base[use]; if (insn->op == IR_PHI) { @@ -2136,7 +2135,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy) len = ir_bitset_len(ctx->vregs_count + 1); todo = ir_bitset_malloc(ctx->vregs_count + 1); - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { ref = *p; insn = &ctx->ir_base[ref]; if (insn->op == IR_PHI) { @@ -2205,7 +2204,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy) ir_mem_free(loc); if (have_constants_or_addresses) { - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { ref = *p; insn = &ctx->ir_base[ref]; if (insn->op == IR_PHI) { diff --git a/ext/opcache/jit/ir/ir_save.c b/ext/opcache/jit/ir/ir_save.c index be9b142c8f324..b12cc267af607 100644 --- a/ext/opcache/jit/ir/ir_save.c +++ b/ext/opcache/jit/ir/ir_save.c @@ -53,7 +53,7 @@ static void ir_save_dessa_moves(const ir_ctx *ctx, int b, ir_block *bb, FILE *f) use_list = &ctx->use_lists[succ_bb->start]; k = ir_phi_input_number(ctx, succ_bb, b); - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + for (i = use_list->count, p = &ctx->use_edges[use_list->refs]; i > 0; p++, i--) { use_ref = *p; use_insn = &ctx->ir_base[use_ref]; if (use_insn->op == IR_PHI) { diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 18192d7f1792a..4f364849390a2 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -667,7 +667,7 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi use_list = &ctx->use_lists[i]; n = use_list->count; - for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; IR_ASSERT(use > 0); use_insn = &ctx->ir_base[use]; @@ -1048,7 +1048,7 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values n++; use_list = &ctx->use_lists[ref]; if (use_list->count > 1) { - for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) { + for (k = use_list->count, p = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) { use = *p; use_insn = &ctx->ir_base[use]; if (use_insn->op == IR_PHI) { @@ -1715,6 +1715,7 @@ static bool ir_may_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref) case IR_OR: case IR_AND: case IR_XOR: + case IR_SHL: return ctx->use_lists[ref].count == 1 && ir_may_promote_i2i(ctx, type, insn->op1) && ir_may_promote_i2i(ctx, type, insn->op2); @@ -1773,6 +1774,7 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) case IR_OR: case IR_AND: case IR_XOR: + case IR_SHL: if (insn->op1 == insn->op2) { insn->op2 = insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref); } else { @@ -2952,6 +2954,14 @@ static ir_ref ir_iter_optimize_condition(ir_ctx *ctx, ir_ref control, ir_ref con { ir_insn *condition_insn = &ctx->ir_base[condition]; + while ((condition_insn->op == IR_BITCAST + || condition_insn->op == IR_ZEXT + || condition_insn->op == IR_SEXT) + && ctx->use_lists[condition].count == 1) { + condition = condition_insn->op1; + condition_insn = &ctx->ir_base[condition]; + } + if (condition_insn->opt == IR_OPT(IR_NOT, IR_BOOL)) { *swap = 1; condition = condition_insn->op1; diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index c4f0eae01c004..3b6cf156ad909 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -1010,6 +1010,7 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(MOD_PWR2) \ _(SDIV_PWR2) \ _(SMOD_PWR2) \ + _(BOOL_NOT) \ _(BOOL_NOT_INT) \ _(ABS_INT) \ _(OP_INT) \ @@ -2223,10 +2224,16 @@ binop_fp: ir_match_fuse_load(ctx, insn->op2, ref); return IR_MOD_INT; case IR_BSWAP: + IR_ASSERT(IR_IS_TYPE_INT(insn->type)); + return IR_OP_INT; case IR_NOT: if (insn->type == IR_BOOL) { - IR_ASSERT(IR_IS_TYPE_INT(ctx->ir_base[insn->op1].type)); // TODO: IR_BOOL_NOT_FP - return IR_BOOL_NOT_INT; + if (ctx->ir_base[insn->op1].type == IR_BOOL) { + return IR_BOOL_NOT; + } else { + IR_ASSERT(IR_IS_TYPE_INT(ctx->ir_base[insn->op1].type)); // TODO: IR_BOOL_NOT_FP + return IR_BOOL_NOT_INT; + } } else { IR_ASSERT(IR_IS_TYPE_INT(insn->type)); return IR_OP_INT; @@ -5054,6 +5061,33 @@ static void ir_emit_abs_int(ir_ctx *ctx, ir_ref def, ir_insn *insn) } } +static void ir_emit_bool_not(ir_ctx *ctx, ir_ref def, ir_insn *insn) +{ + ir_backend_data *data = ctx->data; + dasm_State **Dst = &data->dasm_state; + ir_type type = ctx->ir_base[insn->op1].type; + ir_ref op1 = insn->op1; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); + ir_reg op1_reg = ctx->regs[def][1]; + + IR_ASSERT(def_reg != IR_REG_NONE); + + if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) { + op1_reg = IR_REG_NUM(op1_reg); + ir_emit_load(ctx, type, op1_reg, op1); + } + + if (def_reg != op1_reg) { + | mov Rb(def_reg), Rb(op1_reg) + } + + | xor Rb(def_reg), 1 + + if (IR_REG_SPILLED(ctx->regs[def][0])) { + ir_emit_store(ctx, type, def, def_reg); + } +} + static void ir_emit_bool_not_int(ir_ctx *ctx, ir_ref def, ir_insn *insn) { ir_backend_data *data = ctx->data; @@ -10602,6 +10636,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) case IR_ABS_INT: ir_emit_abs_int(ctx, i, insn); break; + case IR_BOOL_NOT: + ir_emit_bool_not(ctx, i, insn); + break; case IR_BOOL_NOT_INT: ir_emit_bool_not_int(ctx, i, insn); break; From 294888053ae9ead284cace41a9b2783967c69bfa Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 3 Mar 2025 22:15:23 +0100 Subject: [PATCH 016/503] Upgrade i386 branch to Ubuntu 22.04 --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4dad4feea846b..82b67dcd5bcc6 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -139,7 +139,7 @@ jobs: name: LINUX_X32_DEBUG_ZTS runs-on: ubuntu-latest container: - image: ubuntu:20.04 + image: ubuntu:22.04 env: MYSQL_TEST_HOST: mysql PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test From 057ff3519dbef0177e2fd8c2a8138fdadaccd586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 4 Mar 2025 08:42:06 +0100 Subject: [PATCH 017/503] sapi/cli: Print non-default INI settings for `--ini=diff` (#17762) This is a follow-up for php/php-src#17459, updating the command-line flag to not modify the behavior of `--ini`. --- NEWS | 2 +- UPGRADING | 3 ++- sapi/cli/cli.h | 1 + sapi/cli/php_cli.c | 18 +++++++++++++++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 3cf7c303fcc59..cf57d0a36b676 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ PHP NEWS ?? ??? ????, PHP 8.5.0alpha1 - CLI: - . Extended --ini to print INI settings changed from the builtin default. + . Add --ini=diff to print INI settings changed from the builtin default. (timwolla) . Drop support for -z CLI/CGI flag. (nielsdos) . Fixed GH-17956 - development server 404 page does not adapt to mobiles. diff --git a/UPGRADING b/UPGRADING index ab034f7f684b1..d9a2ddc53b308 100644 --- a/UPGRADING +++ b/UPGRADING @@ -136,7 +136,8 @@ PHP 8.5 UPGRADE NOTES - CLI: . Trying to set a process title that is too long with cli_set_process_title() will now fail instead of silently truncating the given title. - . --ini will now print INI settings changed from the builtin default. + . Added a new --ini=diff option to print INI settings changed from the builtin + default. ======================================== 4. Deprecated Functionality diff --git a/sapi/cli/cli.h b/sapi/cli/cli.h index 7097afcf88d9f..85b55af3845d8 100644 --- a/sapi/cli/cli.h +++ b/sapi/cli/cli.h @@ -49,6 +49,7 @@ typedef enum php_cli_mode { PHP_CLI_MODE_REFLECTION_EXT_INFO = 11, PHP_CLI_MODE_REFLECTION_ZEND_EXTENSION = 12, PHP_CLI_MODE_SHOW_INI_CONFIG = 13, + PHP_CLI_MODE_SHOW_INI_DIFF = 14, } php_cli_mode; typedef struct php_cli_server_context { diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 55246cf96c91d..91dd0864c2fbb 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -158,7 +158,7 @@ const opt_struct OPTIONS[] = { {13, 1, "rzendextension"}, {14, 1, "ri"}, {14, 1, "rextinfo"}, - {15, 0, "ini"}, + {15, 2, "ini"}, /* Internal testing option -- may be changed or removed without notice, * including in patch releases. */ {16, 1, "repeat"}, @@ -500,6 +500,7 @@ static void php_cli_usage(char *argv0) " starts with - or script is read from stdin\n" "\n" " --ini Show configuration file names\n" + " --ini=diff Show INI entries that differ from the built-in default\n" "\n" " --rf Show information about function .\n" " --rc Show information about class .\n" @@ -822,7 +823,15 @@ static int do_cli(int argc, char **argv) /* {{{ */ reflection_what = php_optarg; break; case 15: - context.mode = PHP_CLI_MODE_SHOW_INI_CONFIG; + if (php_optarg) { + if (strcmp(php_optarg, "diff") == 0) { + context.mode = PHP_CLI_MODE_SHOW_INI_DIFF; + } else { + param_error = "Unknown argument for --ini\n"; + } + } else { + context.mode = PHP_CLI_MODE_SHOW_INI_CONFIG; + } break; case 16: num_repeats = atoi(php_optarg); @@ -1101,7 +1110,10 @@ static int do_cli(int argc, char **argv) /* {{{ */ zend_printf("Loaded Configuration File: %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)"); zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)"); zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)"); - zend_printf("\n"); + break; + } + case PHP_CLI_MODE_SHOW_INI_DIFF: + { zend_printf("Non-default INI settings:\n"); zend_ini_entry *ini_entry; HashTable *sorted = zend_array_dup(EG(ini_directives)); From 8e39e9c815d4c0e9cc6aaea853de05493f7b8cfa Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Tue, 4 Mar 2025 21:20:21 +0700 Subject: [PATCH 018/503] ext/curl: update `sync-constants.php` consts-ignore list --- ext/curl/sync-constants.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ext/curl/sync-constants.php b/ext/curl/sync-constants.php index 87868bb5b31d9..e24c773a52093 100755 --- a/ext/curl/sync-constants.php +++ b/ext/curl/sync-constants.php @@ -19,6 +19,30 @@ 'CURLOPT_XFERINFODATA', 'CURLOPT_PREREQDATA', 'CURLOPT_DEBUGDATA', + 'CURLOPT_SSL_CTX_DATA', + 'CURLOPT_SOCKOPTDATA', + 'CURLOPT_OPENSOCKETDATA', + 'CURLOPT_SEEKDATA', + 'CURLOPT_FNMATCH_DATA', + 'CURLOPT_CLOSESOCKETDATA', + 'CURLOPT_RESOLVER_START_DATA', + 'CURLOPT_TRAILERDATA', + 'CURLOPT_HSTSREADDATA', + 'CURLOPT_SSH_HOSTKEYDATA', + 'CURLOPT_WRITEDATA', + 'CURLOPT_HEADERDATA', + 'CURLOPT_IOCTLDATA', + 'CURLOPT_SSH_KEYDATA', + 'CURLOPT_INTERLEAVEDATA', + 'CURLOPT_HSTSWRITEDATA', + 'CURLINFO_TYPEMASK', + 'CURLINFO_STRING', + 'CURLINFO_NONE', + 'CURLINFO_MASK', + 'CURLINFO_LONG', + 'CURLINFO_DOUBLE', + 'CURLOPT_CLOSEPOLICY', + 'CURLINFO_END', ]; const IGNORED_PHP_CONSTANTS = [ From cd6524067312e3050155346820bdc91641d1ad42 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 4 Mar 2025 17:09:17 +0000 Subject: [PATCH 019/503] ext/pdo: Add tests for PDO::ATTR_STATEMENT_CLASS attribute (#17969) --- .../pdo_ATTR_STATEMENT_CLASS_basic.phpt | 132 ++++++++++++++++++ .../pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt | 58 ++++++++ ...ENT_CLASS_ctor_arg_no-gc_var_modified.phpt | 49 +++++++ ...TEMENT_CLASS_ctor_arg_no-gc_var_unset.phpt | 49 +++++++ ...o_ATTR_STATEMENT_CLASS_ctor_arg_no_gc.phpt | 47 +++++++ ...ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt | 59 ++++++++ .../pdo_ATTR_STATEMENT_CLASS_errors.phpt | 79 +++++++++++ ...R_STATEMENT_CLASS_with_abstract_class.phpt | 42 ++++++ ...pare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt | 61 ++++++++ ...e_ATTR_STATEMENT_CLASS_ctor_arg_no-gc.phpt | 51 +++++++ ext/pdo/tests/pdo_test.inc | 17 ++- 11 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_modified.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_unset.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no_gc.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_errors.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_with_abstract_class.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt create mode 100644 ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_no-gc.phpt diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt new file mode 100644 index 0000000000000..dfef3bb4839f2 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt @@ -0,0 +1,132 @@ +--TEST-- +PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS overall test +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + +$table = 'pdo_attr_statement_class_basic'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); + +$default = $db->getAttribute(PDO::ATTR_STATEMENT_CLASS); +var_dump($default); + +// Having a public destructor is allowed +class StatementWithPublicDestructor extends PDOStatement { + public function __destruct() { + echo __METHOD__, PHP_EOL; + } +} + +try { + var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPublicDestructor', []])); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPublicDestructor'])); +$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +unset($stmt); + +echo "Class derived from PDOStatement, with private constructor:\n"; +class StatementWithPrivateConstructor extends PDOStatement { + private function __construct($msg) { + echo __METHOD__, PHP_EOL; + var_dump($this); + var_dump($msg); + } +} +var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPrivateConstructor', ['param1']])); +$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +unset($stmt); + +echo "Class derived from a child of PDOStatement:\n"; +class StatementDerivedFromChild extends StatementWithPrivateConstructor { + public function fetchAll($fetch_style = 1, ...$fetch_args): array { + return []; + } +} + +var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementDerivedFromChild', ['param1']])); +$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +var_dump($stmt->fetchAll()); +unset($stmt); + +echo "Reset to default PDOStatement class:\n"; +var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['PDOStatement'])); +$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +var_dump($stmt->fetchAll()); +unset($stmt); + +?> +--CLEAN-- + +--EXPECT-- +array(1) { + [0]=> + string(12) "PDOStatement" +} +bool(true) +bool(true) +StatementWithPublicDestructor::__destruct +Class derived from PDOStatement, with private constructor: +bool(true) +StatementWithPrivateConstructor::__construct +object(StatementWithPrivateConstructor)#2 (1) { + ["queryString"]=> + string(68) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC" +} +string(6) "param1" +Class derived from a child of PDOStatement: +bool(true) +StatementWithPrivateConstructor::__construct +object(StatementDerivedFromChild)#2 (1) { + ["queryString"]=> + string(68) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC" +} +string(6) "param1" +array(0) { +} +Reset to default PDOStatement class: +bool(true) +array(2) { + [0]=> + array(4) { + ["id"]=> + string(1) "1" + [0]=> + string(1) "1" + ["label"]=> + string(1) "a" + [1]=> + string(1) "a" + } + [1]=> + array(4) { + ["id"]=> + string(1) "2" + [0]=> + string(1) "2" + ["label"]=> + string(1) "b" + [1]=> + string(1) "b" + } +} diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt new file mode 100644 index 0000000000000..301a8835eee2e --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt @@ -0,0 +1,58 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed with GC intervention +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, [$this->statementClass, [$this]]); + } +} + +$db = PDOTest::factory(Bar::class); + +$table = 'pdo_attr_statement_class_ctor_arg_gc'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; +$stmt = $db->query($query); + +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); + +?> +--CLEAN-- + +--EXPECT-- +object(Bar)#1 (1) { + ["statementClass"]=> + string(3) "Foo" +} +bool(true) +bool(true) diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_modified.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_modified.phpt new file mode 100644 index 0000000000000..bcf07b1ea8d73 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_modified.phpt @@ -0,0 +1,49 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed without GC intervention as a variable that is modified +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, $a); +$a[0] = 'Bar'; + +$table = 'pdo_attr_statement_class_ctor_arg_no_gc_var_modified'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; +$stmt = $db->query($query); + +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); + +?> +--CLEAN-- + +--EXPECT-- +string(6) "param1" +bool(true) +bool(true) diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_unset.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_unset.phpt new file mode 100644 index 0000000000000..e5d214fea5759 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no-gc_var_unset.phpt @@ -0,0 +1,49 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed without GC intervention as a variable that is unset +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, $a); +unset($a); + +$table = 'pdo_attr_statement_class_ctor_arg_no_gc_var_unset'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; +$stmt = $db->query($query); + +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); + +?> +--CLEAN-- + +--EXPECT-- +string(6) "param1" +bool(true) +bool(true) diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no_gc.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no_gc.phpt new file mode 100644 index 0000000000000..2a111a9ac1947 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_no_gc.phpt @@ -0,0 +1,47 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed without GC intervention +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Foo', ['param1'])); + +$table = 'pdo_attr_statement_class_ctor_arg_no_gc'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; +$stmt = $db->query($query); + +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); + +?> +--CLEAN-- + +--EXPECT-- +string(6) "param1" +bool(true) +bool(true) diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt new file mode 100644 index 0000000000000..61cfe56f779d9 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt @@ -0,0 +1,59 @@ +--TEST-- +PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS overall test +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + +$table = 'pdo_attr_statement_class_cyclic_ctor_args'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); + +$default = $db->getAttribute(PDO::ATTR_STATEMENT_CLASS); +var_dump($default); + +class HoldPdo extends PDOStatement { + private function __construct(public PDO $v) { + var_dump($v); + } +} + +var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['HoldPdo', [$db]])); +$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +var_dump($stmt); + +?> +--CLEAN-- + +--EXPECT-- +array(1) { + [0]=> + string(12) "PDOStatement" +} +bool(true) +object(PDO)#1 (0) { +} +object(HoldPdo)#2 (2) { + ["queryString"]=> + string(79) "SELECT id, label FROM pdo_attr_statement_class_cyclic_ctor_args ORDER BY id ASC" + ["v"]=> + object(PDO)#1 (0) { + } +} diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_errors.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_errors.phpt new file mode 100644 index 0000000000000..c65116d3e5088 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_errors.phpt @@ -0,0 +1,79 @@ +--TEST-- +PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS various error conditions +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, 'not an array'); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + +echo "Unknown class variation:\n"; +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname']); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname', []]); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + +echo "Class not derived from PDOStatement:\n"; +class NotDerived { +} + +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['NotDerived']); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['NotDerived', []]); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + +echo "Class derived from PDOStatement, but with public constructor:\n"; +class DerivedWithPublicConstructor extends PDOStatement { + public function __construct() { } +} + +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedWithPublicConstructor']); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedWithPublicConstructor', []]); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +?> +--EXPECT-- +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS value must be of type array, string given +Unknown class variation: +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be a valid class +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be a valid class +Class not derived from PDOStatement: +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement +TypeError: PDO::setAttribute(): Argument #2 ($value) PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement +Class derived from PDOStatement, but with public constructor: +TypeError: PDO::setAttribute(): Argument #2 ($value) User-supplied statement class cannot have a public constructor +TypeError: PDO::setAttribute(): Argument #2 ($value) User-supplied statement class cannot have a public constructor diff --git a/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_with_abstract_class.phpt b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_with_abstract_class.phpt new file mode 100644 index 0000000000000..339f4ec0be58d --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_with_abstract_class.phpt @@ -0,0 +1,42 @@ +--TEST-- +PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS that is abstract +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); + +abstract class DerivedButAbstract extends PDOStatement { + private function __construct() {} +} + +try { + var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedButAbstract', ['DerivedButAbstract']])); + $stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +?> +--CLEAN-- + +--EXPECT-- +bool(true) +Error: Cannot instantiate abstract class DerivedButAbstract diff --git a/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt b/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt new file mode 100644 index 0000000000000..86d2cfcefd5fd --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt @@ -0,0 +1,61 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed with GC intervention in PDO::prepare() +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, [$this->statementClass, [$this]]); + } +} + +$db = PDOTest::factory(Bar::class); + +$table = 'pdo_prepare_attr_statement_class_ctor_arg_gc'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); + +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; + +$stmt = $db->prepare($query); +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); +$r = $stmt->execute(); +var_dump($r); +?> +--CLEAN-- + +--EXPECT-- +object(Bar)#1 (1) { + ["statementClass"]=> + string(3) "Foo" +} +bool(true) +bool(true) +bool(true) diff --git a/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_no-gc.phpt b/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_no-gc.phpt new file mode 100644 index 0000000000000..bf406b8952750 --- /dev/null +++ b/ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_no-gc.phpt @@ -0,0 +1,51 @@ +--TEST-- +PDO Common: Set PDOStatement class with ctor_args that are freed without GC intervention in PDO::prepare() +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_STATEMENT_CLASS, ['Foo', ['param1']]); + +$table = 'pdo_prepare_attr_statement_class_ctor_arg_no_gc'; +$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')"); +$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')"); + +$query = "SELECT id, label FROM {$table} ORDER BY id ASC"; + +//$stmt = $db->prepare($dummy_query, [PDO::ATTR_STATEMENT_CLASS => ['Foo', ['param1']] ]); +$stmt = $db->prepare($query); + +var_dump($stmt instanceof Foo); +var_dump($stmt->queryString === $query); +$r = $stmt->execute(); +var_dump($r); +?> +--CLEAN-- + +--EXPECT-- +string(6) "param1" +bool(true) +bool(true) +bool(true) diff --git a/ext/pdo/tests/pdo_test.inc b/ext/pdo/tests/pdo_test.inc index 8cd60f68aa519..b44d0b88e77b7 100644 --- a/ext/pdo/tests/pdo_test.inc +++ b/ext/pdo/tests/pdo_test.inc @@ -96,5 +96,20 @@ class PDOTest { }; } } +/** See https://stackoverflow.com/a/3732466 */ +function get_dummy_sql_request(): string +{ + $dsn = getenv('PDOTEST_DSN'); -?> + // Firebird: https://www.firebirdfaq.org/faq30/ + if (str_starts_with($dsn, 'firebird')) { + return "SELECT FIRST 0 FROM (VALUES ('Hello world')"; + } + + // Oracle + if (str_starts_with($dsn, 'oci')) { + return 'SELECT 1 FROM DUAL'; + } + + return 'SELECT 1'; +} From fe8d39afc436f46245848979b2061b0c9d116502 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 4 Mar 2025 22:10:16 +0000 Subject: [PATCH 020/503] ext/pdo: Pack _pdo_dbh_t struct (#17741) This reduces the size from 176 to 152 bytes --- ext/pdo/php_pdo_driver.h | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 1bbdb6f0eceac..9c5986ff8bce8 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -435,42 +435,46 @@ struct _pdo_dbh_t { void *driver_data; /* credentials */ - char *username, *password; + char *username; + char *password; /* if true, then data stored and pointed at by this handle must all be * persistently allocated */ - unsigned is_persistent:1; + bool is_persistent:1; /* if true, driver should act as though a COMMIT were executed between * each executed statement; otherwise, COMMIT must be carried out manually * */ - unsigned auto_commit:1; + bool auto_commit:1; /* if true, the handle has been closed and will not function anymore */ - unsigned is_closed:1; + bool is_closed:1; /* if true, the driver requires that memory be allocated explicitly for * the columns that are returned */ - unsigned alloc_own_columns:1; + bool alloc_own_columns:1; /* if true, commit or rollBack is allowed to be called */ bool in_txn:1; - /* max length a single character can become after correct quoting */ - unsigned max_escaped_char_length:3; - - /* oracle compat; see enum pdo_null_handling */ - unsigned oracle_nulls:2; - /* when set, convert int/floats to strings */ - unsigned stringify:1; + bool stringify:1; /* bitmap for pdo_param_event(s) to skip in dispatch_param_event */ - unsigned skip_param_evt:7; + uint8_t skip_param_evt; + + /* The PDO Error mode; see enum pdo_error_mode */ + uint8_t error_mode; + + /* oracle compat; see enum pdo_null_handling */ + uint8_t oracle_nulls; + + /* Case conversion; see enum pdo_case_conversion */ + uint8_t native_case; + uint8_t desired_case; - /* the sum of the number of bits here and the bit fields preceding should - * equal 32 */ - unsigned _reserved_flags:14; + /* max length a single character can become after correct quoting */ + uint8_t max_escaped_char_length; /* data source string used to open this handle */ const char *data_source; @@ -478,15 +482,14 @@ struct _pdo_dbh_t { /* the global error code. */ pdo_error_type error_code; - - enum pdo_error_mode error_mode; - - enum pdo_case_conversion native_case, desired_case; + /* defaults for fetches */ + uint16_t default_fetch_type; /* persistent hash key associated with this handle */ const char *persistent_id; size_t persistent_id_len; - unsigned int refcount; + + uint32_t refcount; /* driver specific "class" methods for the dbh and stmt */ HashTable *cls_methods[PDO_DBH_DRIVER_METHOD_KIND__MAX]; @@ -503,9 +506,6 @@ struct _pdo_dbh_t { * when PDO::query() fails */ pdo_stmt_t *query_stmt; zend_object *query_stmt_obj; - - /* defaults for fetches */ - enum pdo_fetch_type default_fetch_type; }; /* represents a connection to a database */ From cab120f521fd8406b590115f2b8d32d593ae1e95 Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Wed, 5 Mar 2025 16:19:50 +0700 Subject: [PATCH 021/503] ext/curl: update Caddyfile `basicauth` to `basic_auth` In Caddy 2.8, `basicauth` was renamed to `basic_auth`. This also applies `caddy fmt Caddyfile --overwrite` changes. --- ext/curl/tests/Caddyfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/curl/tests/Caddyfile b/ext/curl/tests/Caddyfile index 1c9432bdb0ba2..30686f0bb9fa2 100644 --- a/ext/curl/tests/Caddyfile +++ b/ext/curl/tests/Caddyfile @@ -12,7 +12,7 @@ respond /serverpush "main response" respond /serverpush/pushed "pushed response" push /serverpush /serverpush/pushed -basicauth /http-basic-auth { - # bcrypt password hash for "password", calculated with 'caddy hash-password' - user $2a$14$yUKl9SGqVTAAqPTzLup.DefsbXXx3kfreNnzpJOUHcIrKnr5lgef2 +basic_auth /http-basic-auth { + # bcrypt password hash for "password", calculated with 'caddy hash-password' + user $2a$14$yUKl9SGqVTAAqPTzLup.DefsbXXx3kfreNnzpJOUHcIrKnr5lgef2 } From 4f5136cf2e57009ba6edb21832218a3b62004664 Mon Sep 17 00:00:00 2001 From: rekmixa Date: Wed, 5 Mar 2025 11:09:04 +0100 Subject: [PATCH 022/503] Allow substituting static for self in final classes Fixes GH-17725 Closes GH-17724 --- UPGRADING | 2 + .../static_to_self.phpt | 85 +++++++++++++++++++ .../static_to_self_in_non_final_class.phpt | 24 ++++++ .../static_to_self_to_unions.phpt | 64 ++++++++++++++ .../union_to_union_1.phpt | 20 +++++ .../union_to_union_2.phpt | 20 +++++ .../union_to_union_3.phpt | 25 ++++++ .../union_to_union_4.phpt | 25 ++++++ .../union_to_union_5.phpt | 24 ++++++ .../union_to_union_6.phpt | 24 ++++++ Zend/zend_inheritance.c | 11 +++ 11 files changed, 324 insertions(+) create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/static_to_self.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_in_non_final_class.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_to_unions.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_1.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_2.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_3.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_4.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_5.phpt create mode 100644 Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_6.phpt diff --git a/UPGRADING b/UPGRADING index d9a2ddc53b308..4129c7349444a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -36,6 +36,8 @@ PHP 8.5 UPGRADE NOTES the behavior of (bool) $object. . The return value of gc_collect_cycles() no longer includes strings and resources that were indirectly collected through cycles. + . It is now allowed to substitute static with self or the concrete class name + in final subclasses. - Intl: . The extension now requires at least ICU 57.1. diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self.phpt new file mode 100644 index 0000000000000..db0b0a4136cc3 --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self.phpt @@ -0,0 +1,85 @@ +--TEST-- +Overriding static return types with self in final class +--FILE-- +method1()); +var_dump($foo->method2()); +var_dump($foo->method3()); + +$bar = new Bar(); + +var_dump($bar->method1()); +var_dump($bar->method2()); +var_dump($bar->method3()); +?> +--EXPECTF-- +object(Foo)#1 (0) { +} +object(Foo)#1 (0) { +} +object(Foo)#1 (0) { +} +object(Bar)#2 (0) { +} +object(Bar)#2 (0) { +} +object(Bar)#2 (0) { +} diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_in_non_final_class.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_in_non_final_class.phpt new file mode 100644 index 0000000000000..13b70f3f74ca0 --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_in_non_final_class.phpt @@ -0,0 +1,24 @@ +--TEST-- +Overriding static return types with self in non-final class +--FILE-- +method1()); +?> +--EXPECTF-- +Fatal error: Declaration of Foo::method1(): Foo must be compatible with A::method1(): static in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_to_unions.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_to_unions.phpt new file mode 100644 index 0000000000000..1e9ca77a03831 --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/static_to_self_to_unions.phpt @@ -0,0 +1,64 @@ +--TEST-- +Overriding static return types with self in final class with union types +--FILE-- +methodScalar()); +var_dump($b->methodIterable1()); +var_dump($b->methodIterable2()); +var_dump($b->methodObject1()); +var_dump($b->methodObject2()); +var_dump($b->methodObject3()); +var_dump($b->methodObject4()); +var_dump($b->methodNullable1()); +var_dump($b->methodNullable2()); +?> +--EXPECTF-- +object(B)#1 (0) { +} +object(B)#1 (0) { +} +array(0) { +} +object(B)#1 (0) { +} +object(B)#1 (0) { +} +object(C)#2 (0) { +} +object(B)#1 (0) { +} +object(B)#1 (0) { +} +NULL diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_1.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_1.phpt new file mode 100644 index 0000000000000..1a73ea5045cc5 --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_1.phpt @@ -0,0 +1,20 @@ +--TEST-- +Overriding return type with type that is not in the interface in final class with union types +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): array must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_2.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_2.phpt new file mode 100644 index 0000000000000..f3f85615944bd --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_2.phpt @@ -0,0 +1,20 @@ +--TEST-- +Overriding static with self and add a type that is not in the interface in final class +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): B|array must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_3.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_3.phpt new file mode 100644 index 0000000000000..0f4e8ea2e189f --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_3.phpt @@ -0,0 +1,25 @@ +--TEST-- +Override static with another implementation of interface in final class +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): C must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_4.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_4.phpt new file mode 100644 index 0000000000000..c4538181c0869 --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_4.phpt @@ -0,0 +1,25 @@ +--TEST-- +Override static with another implementation of interface and add a type that is not in the interface in final class +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): C|array must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_5.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_5.phpt new file mode 100644 index 0000000000000..65d7da1d0210c --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_5.phpt @@ -0,0 +1,24 @@ +--TEST-- +Override static with class that is even not an implementation of interface in final class +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): C must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_6.phpt b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_6.phpt new file mode 100644 index 0000000000000..961027480522e --- /dev/null +++ b/Zend/tests/type_declarations/variance/override_static_with_self/union_to_union_6.phpt @@ -0,0 +1,24 @@ +--TEST-- +Override static with class that is even not an implementation of interface and add a type that is not in the interface in final class +--FILE-- +methodScalar1()); +?> +--EXPECTF-- +Fatal error: Declaration of B::methodScalar1(): C|array must be compatible with A::methodScalar1(): static|bool in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index f5496514fcb7d..807c902276a24 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -502,6 +502,17 @@ static inheritance_status zend_is_class_subtype_of_type( } } + /* If the parent has 'static' as a return type, then final classes could replace it with self */ + if ((ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_STATIC) && (fe_scope->ce_flags & ZEND_ACC_FINAL)) { + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); + if (!fe_ce) { + have_unresolved = 1; + } else if (fe_ce == fe_scope) { + track_class_dependency(fe_ce, fe_class_name); + return INHERITANCE_SUCCESS; + } + } + zend_type *single_type; /* Traverse the list of parent types and check if the current child (FE) From dc6586dd9d4bfa94cd6424a81a91c4f1f183f611 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 5 Mar 2025 10:17:39 -0400 Subject: [PATCH 023/503] Skip mysqli/tests/bug73462 on PPC CI (#17971) * Skip this test on PPC CI Seems to be unfortunately flaky with persistent connections. * use spaces in phpt file --- ext/mysqli/tests/bug73462.phpt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/mysqli/tests/bug73462.phpt b/ext/mysqli/tests/bug73462.phpt index a5ae94acffa80..c4d68ca4f5935 100644 --- a/ext/mysqli/tests/bug73462.phpt +++ b/ext/mysqli/tests/bug73462.phpt @@ -5,6 +5,13 @@ mysqli --SKIPIF-- --FILE-- Date: Wed, 5 Mar 2025 18:40:22 +0100 Subject: [PATCH 024/503] Fix memory leaks in array_any() / array_all() The return value is overwritten, but if the key was not an interned string we should destroy it. Closes GH-17977. --- ext/standard/array.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 7fdc26ccf4afe..99e338a9cd609 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6629,6 +6629,11 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z zend_result result = zend_call_function(&fci, &fci_cache); ZEND_ASSERT(result == SUCCESS); +<<<<<<< HEAD +======= + if (EXPECTED(!Z_ISUNDEF(retval))) { + int retval_true; +>>>>>>> 2701b97011 (Fix memory leaks in array_any() / array_all()) if (UNEXPECTED(EG(exception))) { return FAILURE; @@ -6637,6 +6642,7 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z bool retval_true = zend_is_true(&retval); zval_ptr_dtor(&retval); +<<<<<<< HEAD /* This negates the condition, if negate_condition is true. Otherwise it does nothing with `retval_true`. */ retval_true ^= negate_condition; @@ -6650,6 +6656,10 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z } break; +======= + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return FAILURE; +>>>>>>> 2701b97011 (Fix memory leaks in array_any() / array_all()) } } ZEND_HASH_FOREACH_END(); @@ -6717,7 +6727,11 @@ PHP_FUNCTION(array_any) RETURN_THROWS(); } - RETURN_BOOL(Z_TYPE_P(return_value) != IS_UNDEF); + bool retval = !Z_ISUNDEF_P(return_value); + if (Z_TYPE_P(return_value) == IS_STRING) { + zval_ptr_dtor_str(return_value); + } + RETURN_BOOL(retval); } /* }}} */ @@ -6737,7 +6751,11 @@ PHP_FUNCTION(array_all) RETURN_THROWS(); } - RETURN_BOOL(Z_TYPE_P(return_value) == IS_UNDEF); + bool retval = Z_ISUNDEF_P(return_value); + if (Z_TYPE_P(return_value) == IS_STRING) { + zval_ptr_dtor_str(return_value); + } + RETURN_BOOL(retval); } /* }}} */ From 75cca9f19e5da0e9738e51536282beb23aabe2ef Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:40:22 +0100 Subject: [PATCH 025/503] Fix memory leaks in array_any() / array_all() The return value is overwritten, but if the key was not an interned string we should destroy it. Closes GH-17977. --- NEWS | 3 +++ ext/standard/array.c | 17 +++++++++++++---- ext/standard/tests/array/gh17977.phpt | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 ext/standard/tests/array/gh17977.phpt diff --git a/NEWS b/NEWS index b1f7dbf8e3081..1f2eea0253065 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ PHP NEWS . Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect results for closures created from magic __call()). (timwolla) +- Standard: + . Fix memory leaks in array_any() / array_all(). (nielsdos) + - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) diff --git a/ext/standard/array.c b/ext/standard/array.c index 6bfc0dc9c0403..0c2de2a98a1d9 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6628,7 +6628,8 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z ZVAL_COPY(&args[0], operand); zend_result result = zend_call_function(&fci, &fci_cache); - if (EXPECTED(result == SUCCESS)) { + ZEND_ASSERT(result == SUCCESS); + if (EXPECTED(!Z_ISUNDEF(retval))) { int retval_true; retval_true = zend_is_true(&retval); @@ -6656,7 +6657,7 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z zval_ptr_dtor(&args[0]); zval_ptr_dtor(&args[1]); - if (UNEXPECTED(result != SUCCESS)) { + if (UNEXPECTED(Z_ISUNDEF(retval))) { return FAILURE; } } ZEND_HASH_FOREACH_END(); @@ -6725,7 +6726,11 @@ PHP_FUNCTION(array_any) RETURN_THROWS(); } - RETURN_BOOL(Z_TYPE_P(return_value) != IS_UNDEF); + bool retval = !Z_ISUNDEF_P(return_value); + if (Z_TYPE_P(return_value) == IS_STRING) { + zval_ptr_dtor_str(return_value); + } + RETURN_BOOL(retval); } /* }}} */ @@ -6745,7 +6750,11 @@ PHP_FUNCTION(array_all) RETURN_THROWS(); } - RETURN_BOOL(Z_TYPE_P(return_value) == IS_UNDEF); + bool retval = Z_ISUNDEF_P(return_value); + if (Z_TYPE_P(return_value) == IS_STRING) { + zval_ptr_dtor_str(return_value); + } + RETURN_BOOL(retval); } /* }}} */ diff --git a/ext/standard/tests/array/gh17977.phpt b/ext/standard/tests/array/gh17977.phpt new file mode 100644 index 0000000000000..4a4f344dc4759 --- /dev/null +++ b/ext/standard/tests/array/gh17977.phpt @@ -0,0 +1,18 @@ +--TEST-- +array_any() / array_all() leak +--DESCRIPTION-- +Found in GH-16831#issuecomment-2700410631 +--FILE-- + 1], static fn () => true)); +var_dump(array_all([$key => 1], static fn () => false)); + +?> +--EXPECT-- +bool(true) +bool(false) From 8a699372f27e124abce030ca6175b9768a1455b7 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 6 Mar 2025 15:01:30 +0100 Subject: [PATCH 026/503] Fix flaky DatePeriod test $start and $end use the H:i:s from the current time. If $end happens on a second boundary, $start + 4 days will include $end, thus performing an extra iteration. Fix this by setting H:i:s to 00:00:00. --- ext/date/tests/DatePeriod_no_advance_on_valid.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/date/tests/DatePeriod_no_advance_on_valid.phpt b/ext/date/tests/DatePeriod_no_advance_on_valid.phpt index 6a8a9d0f5d04a..936861ca172c1 100644 --- a/ext/date/tests/DatePeriod_no_advance_on_valid.phpt +++ b/ext/date/tests/DatePeriod_no_advance_on_valid.phpt @@ -3,8 +3,8 @@ Date Period iterators do not advance on valid() --FILE-- getIterator(); From 5fcc8d4cd19552b5ea7c154a0040832b10e4fab6 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 6 Mar 2025 15:24:15 +0100 Subject: [PATCH 027/503] Upgrade security branches to Ubuntu 22.04 20.04 goes out of security support in 2 months. Backporting various commits. See d98963a0713662c567091cdb09a7c9d97a067ce4 See af721c9c361643df13a8137d22de9acde82512e5 See 378b79b90c64997b6fded3381bc5fc8443115b64 Closes GH-17963 --- .github/actions/setup-mssql/action.yml | 2 +- .github/actions/setup-x64/action.yml | 2 +- .github/scripts/setup-slapd.sh | 6 ++++-- .github/workflows/push.yml | 2 +- .github/workflows/root.yml | 5 ++--- Zend/zend_portability.h | 24 ++++++++++++++++++++++++ ext/imap/php_imap.c | 16 +++++++++++++--- ext/imap/php_imap.h | 2 ++ ext/oci8/php_oci8_int.h | 2 ++ ext/opcache/jit/dynasm/dasm_x86.h | 7 +++++++ ext/pdo/pdo_dbh.c | 2 +- ext/pdo_oci/php_pdo_oci_int.h | 9 +++++++++ ext/soap/php_encoding.c | 9 ++++++++- 13 files changed, 75 insertions(+), 13 deletions(-) diff --git a/.github/actions/setup-mssql/action.yml b/.github/actions/setup-mssql/action.yml index c069744a21b59..dd372a5637aac 100644 --- a/.github/actions/setup-mssql/action.yml +++ b/.github/actions/setup-mssql/action.yml @@ -11,4 +11,4 @@ runs: -p 1433:1433 \ --name sql1 \ -h sql1 \ - -d mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 + -d mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04 diff --git a/.github/actions/setup-x64/action.yml b/.github/actions/setup-x64/action.yml index d03a51f455b35..9d49107fb3ca6 100644 --- a/.github/actions/setup-x64/action.yml +++ b/.github/actions/setup-x64/action.yml @@ -7,7 +7,7 @@ runs: set -x sudo service slapd start - docker exec sql1 /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U SA -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" + docker exec sql1 /opt/mssql-tools18/bin/sqlcmd -S 127.0.0.1 -U SA -C -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" sudo locale-gen de_DE ./.github/scripts/setup-slapd.sh diff --git a/.github/scripts/setup-slapd.sh b/.github/scripts/setup-slapd.sh index ec0b2d3060445..fcaa67d0a5f7d 100755 --- a/.github/scripts/setup-slapd.sh +++ b/.github/scripts/setup-slapd.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -ex +set -e # Create TLS certificate sudo mkdir -p /etc/ldap/ssl @@ -42,7 +42,9 @@ sudo sed -e 's|^\s*SLAPD_SERVICES\s*=.*$|SLAPD_SERVICES="ldap:/// ldaps:/// ldap # Configure LDAP database. DBDN=`sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config '(&(olcRootDN=*)(olcSuffix=*))' dn | grep -i '^dn:' | sed -e 's/^dn:\s*//'`; -sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif +if test -f "/etc/ldap/schema/ppolicy.ldif"; then + sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif +fi sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// << EOF dn: $DBDN diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 5264a3d290fac..ddc90935018ba 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -68,7 +68,7 @@ jobs: - debug: false zts: true name: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: git checkout uses: actions/checkout@v4 diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 25b7a6baadef7..2bb895e96b668 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -48,7 +48,7 @@ jobs: with: asan_ubuntu_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') - || '20.04' }} + || '22.04' }} branch: ${{ matrix.branch.ref }} community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} @@ -57,8 +57,7 @@ jobs: run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} ubuntu_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') - || ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) && '22.04') - || '20.04' }} + || '22.04' }} windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} skip_symfony: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_wordpress: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 8f545ecba807c..120b166f7ce8a 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -685,4 +685,28 @@ extern "C++" { # define ZEND_INDIRECT_RETURN #endif +#define __ZEND_DO_PRAGMA(x) _Pragma(#x) +#define _ZEND_DO_PRAGMA(x) __ZEND_DO_PRAGMA(x) +#if defined(__clang__) +# define ZEND_DIAGNOSTIC_IGNORED_START(warning) \ + _Pragma("clang diagnostic push") \ + _ZEND_DO_PRAGMA(clang diagnostic ignored warning) +# define ZEND_DIAGNOSTIC_IGNORED_END \ + _Pragma("clang diagnostic pop") +#elif defined(__GNUC__) +# define ZEND_DIAGNOSTIC_IGNORED_START(warning) \ + _Pragma("GCC diagnostic push") \ + _ZEND_DO_PRAGMA(GCC diagnostic ignored warning) +# define ZEND_DIAGNOSTIC_IGNORED_END \ + _Pragma("GCC diagnostic pop") +#else +# define ZEND_DIAGNOSTIC_IGNORED_START(warning) +# define ZEND_DIAGNOSTIC_IGNORED_END +#endif + +/** @deprecated */ +#define ZEND_CGG_DIAGNOSTIC_IGNORED_START ZEND_DIAGNOSTIC_IGNORED_START +/** @deprecated */ +#define ZEND_CGG_DIAGNOSTIC_IGNORED_END ZEND_DIAGNOSTIC_IGNORED_END + #endif /* ZEND_PORTABILITY_H */ diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index 59244b664d7df..5c45e213aa582 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -695,11 +695,9 @@ PHP_RINIT_FUNCTION(imap) } /* }}} */ -/* {{{ PHP_RSHUTDOWN_FUNCTION */ -PHP_RSHUTDOWN_FUNCTION(imap) +static void free_errorlist(void) { ERRORLIST *ecur = NIL; - STRINGLIST *acur = NIL; if (IMAPG(imap_errorstack) != NIL) { /* output any remaining errors at their original error level */ @@ -715,6 +713,11 @@ PHP_RSHUTDOWN_FUNCTION(imap) mail_free_errorlist(&IMAPG(imap_errorstack)); IMAPG(imap_errorstack) = NIL; } +} + +static void free_stringlist(void) +{ + STRINGLIST *acur = NIL; if (IMAPG(imap_alertstack) != NIL) { /* output any remaining alerts at E_NOTICE level */ @@ -730,6 +733,13 @@ PHP_RSHUTDOWN_FUNCTION(imap) mail_free_stringlist(&IMAPG(imap_alertstack)); IMAPG(imap_alertstack) = NIL; } +} + +/* {{{ PHP_RSHUTDOWN_FUNCTION */ +PHP_RSHUTDOWN_FUNCTION(imap) +{ + free_errorlist(); + free_stringlist(); return SUCCESS; } /* }}} */ diff --git a/ext/imap/php_imap.h b/ext/imap/php_imap.h index ce32d3cda8d91..24019521d61bb 100644 --- a/ext/imap/php_imap.h +++ b/ext/imap/php_imap.h @@ -47,7 +47,9 @@ # endif /* these are used for quota support */ + ZEND_DIAGNOSTIC_IGNORED_START("-Wstrict-prototypes") # include "c-client.h" /* includes mail.h and rfc822.h */ + ZEND_DIAGNOSTIC_IGNORED_END # include "imap4r1.h" /* location of c-client quota functions */ #else # include "mail.h" diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index 171edfa53d24c..0851f74f3f418 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -53,7 +53,9 @@ /* }}} */ #include "ext/standard/php_string.h" +ZEND_DIAGNOSTIC_IGNORED_START("-Wstrict-prototypes") #include +ZEND_DIAGNOSTIC_IGNORED_END extern int le_connection; extern int le_pconnection; diff --git a/ext/opcache/jit/dynasm/dasm_x86.h b/ext/opcache/jit/dynasm/dasm_x86.h index 618925c2d2572..098b226b06a11 100644 --- a/ext/opcache/jit/dynasm/dasm_x86.h +++ b/ext/opcache/jit/dynasm/dasm_x86.h @@ -124,7 +124,14 @@ void dasm_free(Dst_DECL) void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) { dasm_State *D = Dst_REF; +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif D->globals = gl - 10; /* Negative bias to compensate for locals. */ +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); } diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 9544a7215bbf7..d15bb3ac233f5 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -81,7 +81,7 @@ void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate pdo_err = &stmt->error_code; } - strncpy(*pdo_err, sqlstate, 6); + memcpy(*pdo_err, sqlstate, sizeof(pdo_error_type)); /* hash sqlstate to error messages */ msg = pdo_sqlstate_state_to_description(*pdo_err); diff --git a/ext/pdo_oci/php_pdo_oci_int.h b/ext/pdo_oci/php_pdo_oci_int.h index dbffb22d092f8..dd513ff94e061 100644 --- a/ext/pdo_oci/php_pdo_oci_int.h +++ b/ext/pdo_oci/php_pdo_oci_int.h @@ -14,7 +14,14 @@ +----------------------------------------------------------------------+ */ +#ifndef PHP_PDO_OCI_INT_H +#define PHP_PDO_OCI_INT_H + +#include "zend_portability.h" + +ZEND_DIAGNOSTIC_IGNORED_START("-Wstrict-prototypes") #include +ZEND_DIAGNOSTIC_IGNORED_END typedef struct { const char *file; @@ -105,3 +112,5 @@ enum { PDO_OCI_ATTR_MODULE, PDO_OCI_ATTR_CALL_TIMEOUT }; + +#endif /* PHP_PDO_OCI_INT_H */ diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 20f60f48d6a2b..4d389a8c58579 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2388,7 +2388,14 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod if (style == SOAP_ENCODED) { if (soap_version == SOAP_1_1) { smart_str_0(&array_type); - if (strcmp(ZSTR_VAL(array_type.s),"xsd:anyType") == 0) { +#if defined(__GNUC__) && __GNUC__ >= 11 + ZEND_DIAGNOSTIC_IGNORED_START("-Wstringop-overread") +#endif + bool is_xsd_any_type = strcmp(ZSTR_VAL(array_type.s),"xsd:anyType") == 0; +#if defined(__GNUC__) && __GNUC__ >= 11 + ZEND_DIAGNOSTIC_IGNORED_END +#endif + if (is_xsd_any_type) { smart_str_free(&array_type); smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1); } From 918332cf9cb9fa2d6748ce98e9cfbbefe37109d5 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 6 Mar 2025 19:18:38 +0300 Subject: [PATCH 028/503] Fix Symfony tests failures with function JIT --- ext/opcache/jit/zend_jit_ir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index b7956cda52a7e..4ef32415abe76 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -9250,7 +9250,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit, } ce = zend_get_known_class(op_array, opline, opline->op1_type, opline->op1); - if (!func && ce) { + if (!func && ce && (opline->op1_type == IS_CONST || !(ce->ce_flags & ZEND_ACC_TRAIT))) { zval *zv = RT_CONSTANT(opline, opline->op2); zend_string *method_name; @@ -16034,7 +16034,7 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline, zend_class_entry *ce; ce = zend_get_known_class(op_array, opline, opline->op2_type, opline->op2); - if (ce) { + if (ce && (opline->op2_type == IS_CONST || !(ce->ce_flags & ZEND_ACC_TRAIT))) { zval *zv = RT_CONSTANT(opline, opline->op1); zend_string *prop_name; From 9ddc25afe3b8c67338c06a80985bfdeb2d2bd52b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 6 Mar 2025 19:33:41 +0100 Subject: [PATCH 029/503] Simplify array_any(), array_all(), array_find(), array_find_key() (#17978) By returning something more semantically meaningful that SUCCESS/FAILURE we can avoid refcounting for array_all() and array_any(). Also we can avoid resetting the input values to UNDEF. --- ext/standard/array.c | 76 ++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 53 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index a1890b05b57d3..8462492651310 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6591,7 +6591,13 @@ PHP_FUNCTION(array_filter) /* }}} */ /* {{{ Internal function to find an array element for a user closure. */ -static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache fci_cache, zval *result_key, zval *result_value, bool negate_condition) +enum php_array_find_result { + PHP_ARRAY_FIND_EXCEPTION = -1, + PHP_ARRAY_FIND_NONE = 0, + PHP_ARRAY_FIND_SOME = 1, +}; + +static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache fci_cache, zval *result_key, zval *result_value, bool negate_condition) { zend_ulong num_key; zend_string *str_key; @@ -6599,16 +6605,8 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z zval args[2]; zval *operand; - if (result_value != NULL) { - ZVAL_UNDEF(result_value); - } - - if (result_key != NULL) { - ZVAL_UNDEF(result_key); - } - if (zend_hash_num_elements(array) == 0) { - return SUCCESS; + return PHP_ARRAY_FIND_NONE; } ZEND_ASSERT(ZEND_FCI_INITIALIZED(fci)); @@ -6631,7 +6629,7 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z ZEND_ASSERT(result == SUCCESS); if (UNEXPECTED(Z_ISUNDEF(retval))) { - return FAILURE; + return PHP_ARRAY_FIND_EXCEPTION; } bool retval_true = zend_is_true(&retval); @@ -6649,103 +6647,75 @@ static zend_result php_array_find(const HashTable *array, zend_fcall_info fci, z ZVAL_COPY(result_key, &args[1]); } - break; + return PHP_ARRAY_FIND_SOME; } } ZEND_HASH_FOREACH_END(); - return SUCCESS; + return PHP_ARRAY_FIND_NONE; } /* }}} */ /* {{{ Search within an array and returns the first found element value. */ PHP_FUNCTION(array_find) { - zval *array = NULL; + HashTable *array; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(array) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - if (php_array_find(Z_ARR_P(array), fci, fci_cache, NULL, return_value, false) != SUCCESS) { - RETURN_THROWS(); - } - - if (Z_TYPE_P(return_value) == IS_UNDEF) { - RETURN_NULL(); - } + php_array_find(array, fci, fci_cache, NULL, return_value, false); } /* }}} */ /* {{{ Search within an array and returns the first found element key. */ PHP_FUNCTION(array_find_key) { - zval *array = NULL; + HashTable *array; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(array) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - if (php_array_find(Z_ARR_P(array), fci, fci_cache, return_value, NULL, false) != SUCCESS) { - RETURN_THROWS(); - } - - if (Z_TYPE_P(return_value) == IS_UNDEF) { - RETURN_NULL(); - } + php_array_find(array, fci, fci_cache, return_value, NULL, false); } /* }}} */ /* {{{ Checks if at least one array element satisfies a callback function. */ PHP_FUNCTION(array_any) { - zval *array = NULL; + HashTable *array; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(array) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - if (php_array_find(Z_ARR_P(array), fci, fci_cache, return_value, NULL, false) != SUCCESS) { - RETURN_THROWS(); - } - - bool retval = !Z_ISUNDEF_P(return_value); - if (Z_TYPE_P(return_value) == IS_STRING) { - zval_ptr_dtor_str(return_value); - } - RETURN_BOOL(retval); + RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME); } /* }}} */ /* {{{ Checks if all array elements satisfy a callback function. */ PHP_FUNCTION(array_all) { - zval *array = NULL; + HashTable *array; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(array) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - if (php_array_find(Z_ARR_P(array), fci, fci_cache, return_value, NULL, true) != SUCCESS) { - RETURN_THROWS(); - } - - bool retval = Z_ISUNDEF_P(return_value); - if (Z_TYPE_P(return_value) == IS_STRING) { - zval_ptr_dtor_str(return_value); - } - RETURN_BOOL(retval); + RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE); } /* }}} */ From f6c2e40a11c9aba3ed9e9512c66de4e0b1f50343 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 23 Feb 2025 22:36:17 +0100 Subject: [PATCH 030/503] Fix GH-15834: Segfault with hook "simple get" cache slot and minimal JIT The FETCH_OBJ_R VM handler has an optimization that directly enters into a hook if it is a simpler getter hook. This is not compatible with the minimal JIT because the minimal JIT will try to continue executing the opcodes after the FETCH_OBJ_R. To solve this, we check whether the opcode is still the expected one after the execution of the VM handler. If it is not, we know that we are going to execute a simple hook. In that case, exit to the VM. Closes GH-17909. --- NEWS | 4 +++ ext/opcache/jit/zend_jit.c | 42 +++++++++++++++++++++++++----- ext/opcache/tests/jit/gh15834.phpt | 23 ++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 ext/opcache/tests/jit/gh15834.phpt diff --git a/NEWS b/NEWS index 1f2eea0253065..fa4018bf8ed96 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS . Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect results for closures created from magic __call()). (timwolla) +- Opcache: + . Fixed bug GH-15834 (Segfault with hook "simple get" cache slot and minimal + JIT). (nielsdos) + - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 77694e07d132e..2d4ef0bf4fc38 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -1316,7 +1316,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op uint32_t target_label, target_label2; uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info, op1_mem_info; zend_jit_addr op1_addr, op1_def_addr, op2_addr, op2_def_addr, res_addr; - zend_class_entry *ce; + zend_class_entry *ce = NULL; bool ce_is_instanceof; bool on_this; @@ -2335,11 +2335,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op case ZEND_FETCH_OBJ_R: case ZEND_FETCH_OBJ_IS: case ZEND_FETCH_OBJ_W: - if (opline->op2_type != IS_CONST - || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING - || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { - break; - } ce = NULL; ce_is_instanceof = 0; on_this = 0; @@ -2369,6 +2364,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } } + if (opline->op2_type != IS_CONST + || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING + || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { + break; + } if (!zend_jit_fetch_obj(&ctx, opline, op_array, ssa, ssa_op, op1_info, op1_addr, 0, ce, ce_is_instanceof, on_this, 0, 0, NULL, RES_REG_ADDR(), IS_UNKNOWN, @@ -2709,6 +2709,36 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op /* We skip over the DO_FCALL, so decrement call_level ourselves. */ call_level--; } + break; + case ZEND_FETCH_OBJ_R: + if (!zend_jit_handler(&ctx, opline, + zend_may_throw(opline, ssa_op, op_array, ssa))) { + goto jit_failure; + } + + /* Cache slot is only used for IS_CONST op2, so only that can result in hook fast path. */ + if (opline->op2_type == IS_CONST) { + if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) { + if (opline->op1_type == IS_UNUSED) { + ce = op_array->scope; + } else { + ce = NULL; + } + } + + if (!ce || !(ce->ce_flags & ZEND_ACC_FINAL) || ce->num_hooked_props > 0) { + /* If a simple hook is called, exit to the VM. */ + ir_ref if_hook_enter = ir_IF(jit_CMP_IP(jit, IR_EQ, opline + 1)); + ir_IF_FALSE(if_hook_enter); + if (GCC_GLOBAL_REGS) { + ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + } else { + ir_RETURN(ir_CONST_I32(1)); /* ZEND_VM_ENTER */ + } + ir_IF_TRUE(if_hook_enter); + } + } + break; default: if (!zend_jit_handler(&ctx, opline, diff --git a/ext/opcache/tests/jit/gh15834.phpt b/ext/opcache/tests/jit/gh15834.phpt new file mode 100644 index 0000000000000..a8cc6ce7a15d6 --- /dev/null +++ b/ext/opcache/tests/jit/gh15834.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-15834 (Segfault with hook "simple get" cache slot and minimal JIT) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1111 +--FILE-- + $this->_prop; + } +} + +$a = new A; +for ($i=0;$i<5;$i++) { + echo $a->prop; + $a->_prop++; +} +?> +--EXPECT-- +12345 From d9e39f5c6f70a4de3c201b436f447dc069d49e0e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 6 Mar 2025 21:53:45 +0300 Subject: [PATCH 031/503] Fix JIT for INIT_STATIC_METHOD_CALL in a closure --- ext/opcache/jit/zend_jit_ir.c | 2 +- .../jit/init_static_method_call_001.phpt | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/init_static_method_call_001.phpt diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 4ef32415abe76..a3aae9b921f25 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -9353,7 +9353,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit, if (opline->op1_type == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { - if (op_array->fn_flags & ZEND_ACC_STATIC) { + if (!op_array->scope || (op_array->fn_flags & ZEND_ACC_STATIC)) { scope_ref = ir_LOAD_A(jit_EX(This.value.ref)); } else { scope_ref = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce))); diff --git a/ext/opcache/tests/jit/init_static_method_call_001.phpt b/ext/opcache/tests/jit/init_static_method_call_001.phpt new file mode 100644 index 0000000000000..b6f1b95cc1e23 --- /dev/null +++ b/ext/opcache/tests/jit/init_static_method_call_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +JIT INIT_STATIC_METHOD_CALL: 001 Invalid scope +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +int(15) From cc70838dc923f2f5896d2faa1240fb2e5100d24f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 6 Mar 2025 23:00:53 +0300 Subject: [PATCH 032/503] Merge IR IR commit: 0441281e95ce9736131eddc71ce666389dcccd4b --- ext/opcache/jit/ir/ir_gcm.c | 7 ++++--- ext/opcache/jit/ir/ir_sccp.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ext/opcache/jit/ir/ir_gcm.c b/ext/opcache/jit/ir/ir_gcm.c index be8744ef198fd..396ba2d7f7c7b 100644 --- a/ext/opcache/jit/ir/ir_gcm.c +++ b/ext/opcache/jit/ir/ir_gcm.c @@ -401,9 +401,10 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b) for (i = 1; i < clones_count; i++) { clones[i].ref = clone = ir_emit(ctx, insn->optx, insn->op1, insn->op2, insn->op3); insn = &ctx->ir_base[ref]; - if (insn->op1 > 0) ir_use_list_add(ctx, insn->op1, clone); - if (insn->op2 > 0) ir_use_list_add(ctx, insn->op2, clone); - if (insn->op3 > 0) ir_use_list_add(ctx, insn->op3, clone); + /* Depending on the flags in IR_OPS, these can be references or data. */ + if (insn->op1 > 0 && insn->inputs_count >= 1) ir_use_list_add(ctx, insn->op1, clone); + if (insn->op2 > 0 && insn->inputs_count >= 2) ir_use_list_add(ctx, insn->op2, clone); + if (insn->op3 > 0 && insn->inputs_count >= 3) ir_use_list_add(ctx, insn->op3, clone); } /* Reconstruct IR: Update DEF->USE lists, CFG mapping and etc */ diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 4f364849390a2..b4f2257744145 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -3067,7 +3067,7 @@ static void ir_iter_optimize_if(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqu static void ir_iter_optimize_guard(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqueue *worklist) { - bool swap; + bool swap = 0; ir_ref condition = ir_iter_optimize_condition(ctx, insn->op1, insn->op2, &swap); if (swap) { From bac1ed6579cf7431d2c46957b69d7d757d406d82 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 6 Mar 2025 21:54:30 +0100 Subject: [PATCH 033/503] Add test for GH-17966 This was fixed via https://github.com/dstogov/ir/pull/109 which was merged in cc70838dc923f2f5896d2faa1240fb2e5100d24f. --- NEWS | 1 + ext/opcache/tests/jit/gh17966.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 ext/opcache/tests/jit/gh17966.phpt diff --git a/NEWS b/NEWS index fa4018bf8ed96..404290dcf615b 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS - Opcache: . Fixed bug GH-15834 (Segfault with hook "simple get" cache slot and minimal JIT). (nielsdos) + . Fixed bug GH-17966 (Symfony JIT 1205 assertion failure). (nielsdos) - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/ext/opcache/tests/jit/gh17966.phpt b/ext/opcache/tests/jit/gh17966.phpt new file mode 100644 index 0000000000000..f9983ad4c2b36 --- /dev/null +++ b/ext/opcache/tests/jit/gh17966.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-17966 (Symfony JIT 1205 assertion failure) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1205 +--FILE-- + +--EXPECT-- +float(2.5) +float(1.25) From 972d6b6664ec19b1f8ae2a87e2c9a9fedf80e80d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 7 Mar 2025 01:09:28 +0300 Subject: [PATCH 034/503] Fix JIT for INIT_STATIC_METHOD_CALL in a closure --- ext/opcache/jit/zend_jit_ir.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index a3aae9b921f25..ca3ac174e5db0 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -9353,8 +9353,18 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit, if (opline->op1_type == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { - if (!op_array->scope || (op_array->fn_flags & ZEND_ACC_STATIC)) { + if (op_array->fn_flags & ZEND_ACC_STATIC) { scope_ref = ir_LOAD_A(jit_EX(This.value.ref)); + } else if (op_array->fn_flags & ZEND_ACC_CLOSURE) { + ir_ref if_object, values = IR_UNUSED; + + if_object = ir_IF(ir_EQ(jit_Z_TYPE_ref(jit, jit_EX(This)), ir_CONST_U8(IS_OBJECT))); + ir_IF_TRUE(if_object); + ir_END_PHI_list(values, + ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce)))); + ir_IF_FALSE(if_object); + ir_END_PHI_list(values, ir_LOAD_A(jit_EX(This.value.ref))); + ir_PHI_list(values); } else { scope_ref = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce))); } From 5885b9490c85a99bf700e0fa35207edc7f995cdd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 7 Mar 2025 02:30:30 +0300 Subject: [PATCH 035/503] Fix function JIT for Wordpress unit tests --- ext/opcache/jit/zend_jit_ir.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index b7841fd1701a8..32d632f5b96ed 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -3558,6 +3558,8 @@ static void jit_IF_TRUE_FALSE_ex(zend_jit_ctx *jit, ir_ref if_ref, ir_ref true_b } } +static void zend_jit_case_start(zend_jit_ctx *jit, int switch_b, int case_b, ir_ref switch_ref); + static void _zend_jit_add_predecessor_ref(zend_jit_ctx *jit, int b, int pred, ir_ref ref) { int i, *p; @@ -3580,6 +3582,9 @@ static void _zend_jit_add_predecessor_ref(zend_jit_ctx *jit, int b, int pred, ir } else if (jit->ctx.ir_base[ref].op == IR_IF) { jit_IF_TRUE_FALSE_ex(jit, ref, b); ref = ir_LOOP_END(); + } else if (jit->ctx.ir_base[ref].op == IR_SWITCH) { + zend_jit_case_start(jit, pred, b, ref); + ref = ir_LOOP_END(); } else if (jit->ctx.ir_base[ref].op == IR_UNREACHABLE) { ir_BEGIN(ref); ref = ir_LOOP_END(); From 5e8aff2c5fdd4c278446f85b267aab680a9fdca3 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Fri, 7 Mar 2025 10:39:14 -0400 Subject: [PATCH 036/503] Remove "Notify Slack" on ppc nightly workflow (#17993) We get weird failures at here, and Ilija was talking about possibly removing it in general. --- .github/workflows/nightly.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7993c1b6e3586..c9e6850604312 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -76,11 +76,6 @@ jobs: with: runTestsParameters: >- --asan -x - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} ALPINE: if: inputs.run_alpine name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS From 1b9d659c3fbd5f778a39873325335aa67d8852cd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 7 Mar 2025 19:28:51 +0300 Subject: [PATCH 037/503] Fix register allocarion for result of ASSIGN_OBJ (#17994) This fixes few failures in Symfony unit tests with function JIT --- ext/opcache/jit/zend_jit_ir.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 32d632f5b96ed..32c58f24c7cd2 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -14748,13 +14748,6 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, // CACHE_PTR_EX(cache_slot + 2, NULL); } - if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) { - zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); - if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) { - return 0; - } - } - ir_END_list(end_inputs); ir_IF_FALSE(if_has_prop_info); } @@ -14820,12 +14813,6 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, arg3, arg4); - if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) { - zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); - if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) { - return 0; - } - } ir_END_list(end_inputs); } } @@ -14838,7 +14825,14 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, return 0; } } else { - if (!zend_jit_assign_to_variable(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, res_addr, 0, 0)) { + zend_jit_addr real_res_addr; + + if (res_addr && Z_MODE(res_addr) == IS_REG) { + real_res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); + } else { + real_res_addr = res_addr; + } + if (!zend_jit_assign_to_variable(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, real_res_addr, 0, 0)) { return 0; } } @@ -14888,12 +14882,6 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, ir_ADD_OFFSET(run_time_cache, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS), arg5); - if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) { - zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); - if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) { - return 0; - } - } ir_END_list(end_inputs); } @@ -14914,6 +14902,13 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline); } + if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) { + zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); + if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) { + return 0; + } + } + if (may_throw) { zend_jit_check_exception(jit); } From 97402d5ab58018c90e9a80495c12fc423990dcce Mon Sep 17 00:00:00 2001 From: bogdanungureanu Date: Wed, 5 Mar 2025 13:04:09 +0200 Subject: [PATCH 038/503] ext/intl: Add DECIMAL_COMPACT_SHORT and DECIMAL_COMPACT_LONG for NumberFormatter class close GH-17975 --- ext/intl/formatter/formatter.stub.php | 4 ++ ext/intl/formatter/formatter_arginfo.h | 14 ++++- .../formatter_format_decimal_compact.phpt | 57 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/formatter_format_decimal_compact.phpt diff --git a/ext/intl/formatter/formatter.stub.php b/ext/intl/formatter/formatter.stub.php index e335698688d64..4445005c41705 100644 --- a/ext/intl/formatter/formatter.stub.php +++ b/ext/intl/formatter/formatter.stub.php @@ -11,6 +11,10 @@ class NumberFormatter public const int PATTERN_DECIMAL = UNKNOWN; /** @cvalue UNUM_DECIMAL */ public const int DECIMAL = UNKNOWN; + /** @cvalue UNUM_DECIMAL_COMPACT_SHORT */ + public const int DECIMAL_COMPACT_SHORT = UNKNOWN; + /** @cvalue UNUM_DECIMAL_COMPACT_LONG */ + public const int DECIMAL_COMPACT_LONG = UNKNOWN; /** @cvalue UNUM_CURRENCY */ public const int CURRENCY = UNKNOWN; /** @cvalue UNUM_PERCENT */ diff --git a/ext/intl/formatter/formatter_arginfo.h b/ext/intl/formatter/formatter_arginfo.h index 0e3d8b797e721..c7fd28c3a9f77 100644 --- a/ext/intl/formatter/formatter_arginfo.h +++ b/ext/intl/formatter/formatter_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: caaa6ff408bfd88ec9bb998ffd753f4de971ccff */ + * Stub hash: 05ab9fb3ba33163b2100e2773d70f67e110ecefc */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter___construct, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) @@ -137,6 +137,18 @@ static zend_class_entry *register_class_NumberFormatter(void) zend_declare_typed_class_constant(class_entry, const_DECIMAL_name, &const_DECIMAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_DECIMAL_name); + zval const_DECIMAL_COMPACT_SHORT_value; + ZVAL_LONG(&const_DECIMAL_COMPACT_SHORT_value, UNUM_DECIMAL_COMPACT_SHORT); + zend_string *const_DECIMAL_COMPACT_SHORT_name = zend_string_init_interned("DECIMAL_COMPACT_SHORT", sizeof("DECIMAL_COMPACT_SHORT") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_DECIMAL_COMPACT_SHORT_name, &const_DECIMAL_COMPACT_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_DECIMAL_COMPACT_SHORT_name); + + zval const_DECIMAL_COMPACT_LONG_value; + ZVAL_LONG(&const_DECIMAL_COMPACT_LONG_value, UNUM_DECIMAL_COMPACT_LONG); + zend_string *const_DECIMAL_COMPACT_LONG_name = zend_string_init_interned("DECIMAL_COMPACT_LONG", sizeof("DECIMAL_COMPACT_LONG") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_DECIMAL_COMPACT_LONG_name, &const_DECIMAL_COMPACT_LONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_DECIMAL_COMPACT_LONG_name); + zval const_CURRENCY_value; ZVAL_LONG(&const_CURRENCY_value, UNUM_CURRENCY); zend_string *const_CURRENCY_name = zend_string_init_interned("CURRENCY", sizeof("CURRENCY") - 1, 1); diff --git a/ext/intl/tests/formatter_format_decimal_compact.phpt b/ext/intl/tests/formatter_format_decimal_compact.phpt new file mode 100644 index 0000000000000..2c78f8787e0f4 --- /dev/null +++ b/ext/intl/tests/formatter_format_decimal_compact.phpt @@ -0,0 +1,57 @@ +--TEST-- +numfmt_format_currency() icu >= 4.8 +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +en_UK: short = 1.2M +en_UK: long = 1.2 million +en_US: short = 1.2M +en_US: long = 1.2 million +ru: short = 1,2 млн +ru: long = 1,2 миллиона +zh_CN: short = 123万 +zh_CN: long = 123万 +ro: short = 1,2 mil. +ro: long = 1,2 milioane +uk: short = 1,2 млн +uk: long = 1,2 мільйона +en: short = 1.2M +en: long = 1.2 million +bg: short = 1,2 млн. +bg: long = 1,2 милиона \ No newline at end of file From cd88e9f1f4424b47b876ee1ad1161d3f53e7f912 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 7 Mar 2025 18:02:52 +0000 Subject: [PATCH 039/503] [skip ci] NEWS/UPGRADING --- NEWS | 2 ++ UPGRADING | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/NEWS b/NEWS index cf57d0a36b676..68e7df9d84f7f 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,8 @@ PHP NEWS . Bumped ICU requirement to ICU >= 57.1. (cmb) . IntlDateFormatter::setTimeZone()/datefmt_set_timezone() throws an exception with uninitialised classes or clone failure. (David Carlier) + . Added DECIMAL_COMPACT_SHORT/DECIMAL_COMPACT_LONG for NumberFormatter class. + (BogdanUngureanu) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 4129c7349444a..21cf4d3062df7 100644 --- a/UPGRADING +++ b/UPGRADING @@ -291,6 +291,10 @@ PHP 8.5 UPGRADE NOTES . CURLINFO_HTTPAUTH_USED. . CURLINFO_PROXYAUTH_USED. +- Intl: + . DECIMAL_COMPACT_SHORT. + . DECIMAL_COMPACT_LONG. + - POSIX: . POSIX_SC_OPEN_MAX. From 07ceadf7d9bcb398fd3b3befa9fdf0df3a96dc8d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 6 Mar 2025 22:26:34 +0000 Subject: [PATCH 040/503] Fix GH-17984: gd calls with array arguments. close GH-17985 --- NEWS | 2 ++ ext/gd/gd.c | 8 +++---- ext/gd/tests/gh17984.phpt | 44 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 ext/gd/tests/gh17984.phpt diff --git a/NEWS b/NEWS index 352dce95e7a42..d72d262bbc42c 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ PHP NEWS - GD: . Fixed bug GH-17772 (imagepalettetotruecolor crash with memory_limit=2M). (David Carlier) + . Fixed bug GH-17984 (calls with arguments as array with references). + (David Carlier) - LDAP: . Fixed bug GH-17704 (ldap_search fails when $attributes contains a diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 847e0835bad4f..2585923edcc22 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3417,7 +3417,7 @@ PHP_FUNCTION(imageconvolution) } for (i=0; i<3; i++) { - if ((var = zend_hash_index_find(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) { + if ((var = zend_hash_index_find_deref(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) { if (zend_hash_num_elements(Z_ARRVAL_P(var)) != 3 ) { zend_argument_value_error(2, "must be a 3x3 array, matrix[%d] only has %d elements", i, zend_hash_num_elements(Z_ARRVAL_P(var))); RETURN_THROWS(); @@ -3697,7 +3697,7 @@ PHP_FUNCTION(imageaffine) } for (i = 0; i < nelems; i++) { - if ((zval_affine_elem = zend_hash_index_find(Z_ARRVAL_P(z_affine), i)) != NULL) { + if ((zval_affine_elem = zend_hash_index_find_deref(Z_ARRVAL_P(z_affine), i)) != NULL) { switch (Z_TYPE_P(zval_affine_elem)) { case IS_LONG: affine[i] = Z_LVAL_P(zval_affine_elem); @@ -3873,7 +3873,7 @@ PHP_FUNCTION(imageaffinematrixconcat) } for (i = 0; i < 6; i++) { - if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m1), i)) != NULL) { + if ((tmp = zend_hash_index_find_deref(Z_ARRVAL_P(z_m1), i)) != NULL) { switch (Z_TYPE_P(tmp)) { case IS_LONG: m1[i] = Z_LVAL_P(tmp); @@ -3890,7 +3890,7 @@ PHP_FUNCTION(imageaffinematrixconcat) } } - if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m2), i)) != NULL) { + if ((tmp = zend_hash_index_find_deref(Z_ARRVAL_P(z_m2), i)) != NULL) { switch (Z_TYPE_P(tmp)) { case IS_LONG: m2[i] = Z_LVAL_P(tmp); diff --git a/ext/gd/tests/gh17984.phpt b/ext/gd/tests/gh17984.phpt new file mode 100644 index 0000000000000..c46c455799e0f --- /dev/null +++ b/ext/gd/tests/gh17984.phpt @@ -0,0 +1,44 @@ +--TEST-- +GH-17984: array of references handling +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +object(GdImage)#2 (0) { +} +array(6) { + [0]=> + float(2028) + [1]=> + float(46) + [2]=> + float(138) + [3]=> + float(4) + [4]=> + float(233) + [5]=> + float(7) +} +bool(true) +bool(true) +bool(true) From fc09eb21db722cc31cea0a8687c9bfdb05bb1218 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 7 Mar 2025 18:31:00 +0000 Subject: [PATCH 041/503] [skip ci] fix NEWS entry --- NEWS | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index d72d262bbc42c..46b0934b8700e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.19 +- GD: + . Fixed bug GH-17984 (calls with arguments as array with references). + (David Carlier) + - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) @@ -34,8 +38,6 @@ PHP NEWS - GD: . Fixed bug GH-17772 (imagepalettetotruecolor crash with memory_limit=2M). (David Carlier) - . Fixed bug GH-17984 (calls with arguments as array with references). - (David Carlier) - LDAP: . Fixed bug GH-17704 (ldap_search fails when $attributes contains a From 6083dc09a3d760074941c17e7eb10e606768a5fe Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:37:40 +0100 Subject: [PATCH 042/503] Fix GH-17991: Assertion failure dom_attr_value_write Closes GH-17995. --- NEWS | 3 +++ ext/dom/php_dom.c | 7 ++++--- ext/dom/tests/gh17991.phpt | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 ext/dom/tests/gh17991.phpt diff --git a/NEWS b/NEWS index 77446730edb4c..34f75683d7170 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ PHP NEWS . Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect results for closures created from magic __call()). (timwolla) +- DOM: + . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) + - Opcache: . Fixed bug GH-15834 (Segfault with hook "simple get" cache slot and minimal JIT). (nielsdos) diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index f84f17fee2e9b..819d22712ebfc 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -372,13 +372,14 @@ static zend_always_inline const dom_prop_handler *dom_get_prop_handler(const dom if (obj->prop_handler != NULL) { if (cache_slot && *cache_slot == obj->prop_handler) { - hnd = *(cache_slot + 1); + hnd = cache_slot[1]; } if (!hnd) { hnd = zend_hash_find_ptr(obj->prop_handler, name); if (cache_slot) { - *cache_slot = obj->prop_handler; - *(cache_slot + 1) = (void *) hnd; + cache_slot[0] = obj->prop_handler; + cache_slot[1] = (void *) hnd; + cache_slot[2] = NULL; } } } diff --git a/ext/dom/tests/gh17991.phpt b/ext/dom/tests/gh17991.phpt new file mode 100644 index 0000000000000..4fc2c5b4ec1eb --- /dev/null +++ b/ext/dom/tests/gh17991.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-17991 (Assertion failure dom_attr_value_write) +--EXTENSIONS-- +dom +--FILE-- +value = new Test); +} +$box = new Box(); +test($box); +test($attr); +?> +--EXPECTF-- +object(Test)#%d (0) { +} + +Fatal error: Uncaught TypeError: Cannot assign Test to property DOMAttr::$value of type string in %s:%d +Stack trace: +#0 %s(%d): test(Object(DOMAttr)) +#1 {main} + thrown in %s on line %d From 38e8725becf71a9cbd1fc8e8163b69ee1e2eb0d6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 27 Feb 2025 18:56:39 +0100 Subject: [PATCH 043/503] Fix GH-17941: Stack-use-after-return with lazy objects and hooks zend_std_write_property() can return the variable pointer, but the code was using a local variable, and so a pointer to a local variable could be returned. Fix this by using the value pointer instead of the backup value was written. This can be more efficient on master by using the safe_assign helper. Closes GH-17947. --- NEWS | 2 ++ Zend/tests/lazy_objects/gh17941.phpt | 26 ++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 5 +++++ 3 files changed, 33 insertions(+) create mode 100644 Zend/tests/lazy_objects/gh17941.phpt diff --git a/NEWS b/NEWS index 34f75683d7170..576a045a02294 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS child class). (ilutov) . Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect results for closures created from magic __call()). (timwolla) + . Fixed bug GH-17941 (Stack-use-after-return with lazy objects and hooks). + (nielsdos) - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) diff --git a/Zend/tests/lazy_objects/gh17941.phpt b/Zend/tests/lazy_objects/gh17941.phpt new file mode 100644 index 0000000000000..6af6355b99573 --- /dev/null +++ b/Zend/tests/lazy_objects/gh17941.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-17941 (Stack-use-after-return with lazy objects and hooks) +--FILE-- + $this->prop; set($x) => $this->prop = $x;} +} + +$rc = new ReflectionClass(SubClass::class); +$obj = $rc->newLazyProxy(function ($object) { + echo "init\n"; + return new SubClass; +}); + +function foo(SubClass $x) { + $x->prop = 1; + var_dump($x->prop); +} + +foo($obj); + +?> +--EXPECT-- +init +int(1) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 5a4e4b3ea3a1c..bba40c6bd41ec 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1198,6 +1198,11 @@ lazy_init:; variable_ptr = zend_std_write_property(zobj, name, &backup, cache_slot); zval_ptr_dtor(&backup); + + if (variable_ptr == &backup) { + variable_ptr = value; + } + return variable_ptr; } /* }}} */ From 2634622d3dd0a4d41426465712d271be0e115a75 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 8 Mar 2025 11:12:24 +0100 Subject: [PATCH 044/503] Fix uninitialized memory accesses in DOM iterator --- ext/dom/dom_iterators.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index adc5835f9d8bd..ff63342595ae9 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -278,15 +278,13 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } - iterator = emalloc(sizeof(php_dom_iterator)); + iterator = emalloc(sizeof(*iterator)); + memset(iterator, 0, sizeof(*iterator)); zend_iterator_init(&iterator->intern); - iterator->cache_tag.modification_nr = 0; ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &php_dom_iterator_funcs; - ZVAL_UNDEF(&iterator->curobj); - intern = Z_DOMOBJ_P(object); objmap = (dom_nnodemap_object *)intern->ptr; if (objmap != NULL) { From 868959350ffd1252b00bfbcdcae8c2d7e229f66c Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 7 Mar 2025 20:47:43 +0100 Subject: [PATCH 045/503] Fix incorrect handling of hooked props without get hook in get_object_vars() Fixes GH-17988 Closes GH-17997 --- NEWS | 2 ++ Zend/tests/property_hooks/gh17988.phpt | 40 ++++++++++++++++++++++++++ Zend/zend_builtin_functions.c | 3 +- ext/json/json_encoder.c | 3 +- 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/property_hooks/gh17988.phpt diff --git a/NEWS b/NEWS index 576a045a02294..aa8ffd81ab6ad 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ PHP NEWS results for closures created from magic __call()). (timwolla) . Fixed bug GH-17941 (Stack-use-after-return with lazy objects and hooks). (nielsdos) + . Fixed bug GH-17988 (Incorrect handling of hooked props without get hook in + get_object_vars()). (ilutov) - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) diff --git a/Zend/tests/property_hooks/gh17988.phpt b/Zend/tests/property_hooks/gh17988.phpt new file mode 100644 index 0000000000000..629eec60d010b --- /dev/null +++ b/Zend/tests/property_hooks/gh17988.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-17988: Incorrect handling of hooked properties without get hook in get_object_vars() +--FILE-- + $value; + } +} + +$c = new C; +$c->prop = 42; + +var_dump($c); +var_dump(get_object_vars($c)); +var_export($c); +echo "\n"; +var_dump(json_encode($c)); +var_dump((array)$c); + +?> +--EXPECTF-- +object(C)#%d (1) { + ["prop"]=> + string(2) "42" +} +array(1) { + ["prop"]=> + string(2) "42" +} +\C::__set_state(array( + 'prop' => '42', +)) +string(13) "{"prop":"42"}" +array(1) { + ["prop"]=> + string(2) "42" +} diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index f2f6b80fc66d7..8ed7939200c79 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -840,7 +840,7 @@ ZEND_FUNCTION(get_object_vars) } const char *unmangled_name_cstr = zend_get_unmangled_property_name(prop_info->name); zend_string *unmangled_name = zend_string_init(unmangled_name_cstr, strlen(unmangled_name_cstr), false); - zend_read_property_ex(prop_info->ce, zobj, unmangled_name, /* silent */ true, &tmp); + value = zend_read_property_ex(prop_info->ce, zobj, unmangled_name, /* silent */ true, &tmp); zend_string_release_ex(unmangled_name, false); if (EG(exception)) { zend_release_properties(properties); @@ -848,7 +848,6 @@ ZEND_FUNCTION(get_object_vars) ZVAL_UNDEF(return_value); RETURN_THROWS(); } - value = &tmp; } Z_TRY_ADDREF_P(value); diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 7c44a7f5c7a71..4145bc2b6154a 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -283,13 +283,12 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, if ((prop_info->flags & ZEND_ACC_VIRTUAL) && !prop_info->hooks[ZEND_PROPERTY_HOOK_GET]) { continue; } - zend_read_property_ex(prop_info->ce, Z_OBJ_P(val), prop_info->name, /* silent */ true, &tmp); + data = zend_read_property_ex(prop_info->ce, Z_OBJ_P(val), prop_info->name, /* silent */ true, &tmp); if (EG(exception)) { PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc); zend_release_properties(prop_ht); return FAILURE; } - data = &tmp; } if (need_comma) { From 9acfe6e11cd7b6fb16b365482ca00ca939a71a38 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 7 Mar 2025 22:28:19 +0100 Subject: [PATCH 046/503] Fix skipped lazy init on primed SIMPLE_WRITE Go through the normal assignment path, which includes an IS_UNDEF check. Fixes GH-17998 Closes GH-17999 --- NEWS | 2 + Zend/tests/lazy_objects/gh17998.phpt | 31 ++ Zend/zend_vm_def.h | 18 +- Zend/zend_vm_execute.h | 648 +++++++++++++-------------- 4 files changed, 366 insertions(+), 333 deletions(-) create mode 100644 Zend/tests/lazy_objects/gh17998.phpt diff --git a/NEWS b/NEWS index aa8ffd81ab6ad..87c99560ec350 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS (nielsdos) . Fixed bug GH-17988 (Incorrect handling of hooked props without get hook in get_object_vars()). (ilutov) + . Fixed bug GH-17998 (Skipped lazy object initialization on primed + SIMPLE_WRITE cache). (ilutov) - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) diff --git a/Zend/tests/lazy_objects/gh17998.phpt b/Zend/tests/lazy_objects/gh17998.phpt new file mode 100644 index 0000000000000..12d22b4704a13 --- /dev/null +++ b/Zend/tests/lazy_objects/gh17998.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-17998: Skipped lazy init on primed SIMPLE_WRITE +--FILE-- + $value; + } +} + +$nonLazy = new C; + +$lazy = (new ReflectionClass(C::class))->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +function foo(C $c) { + $c->prop = 1; + var_dump($c->prop); +} + +foo($nonLazy); +foo($lazy); + +?> +--EXPECT-- +int(1) +init +int(1) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index eea3a4f7e2da1..a4fa8063a5bd4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2450,12 +2450,14 @@ ZEND_VM_C_LABEL(assign_object): void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +ZEND_VM_C_LABEL(assign_obj_simple): property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); ZEND_VM_C_GOTO(free_and_exit_assign_obj); @@ -2527,14 +2529,12 @@ ZEND_VM_C_LABEL(fast_assign_obj): } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - ZEND_VM_C_GOTO(free_and_exit_assign_obj); - } else { - ZEND_VM_C_GOTO(fast_assign_obj); + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + ZEND_VM_C_GOTO(assign_obj_simple); } /* Fall through to write_property for hooks. */ } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cb4f3747a02b0..2f6f0af2d872c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -24037,12 +24037,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -24114,14 +24116,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -24191,12 +24191,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -24268,14 +24270,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -24345,12 +24345,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -24422,14 +24424,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -24499,12 +24499,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -24576,14 +24578,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -27028,12 +27028,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -27105,14 +27107,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -27182,12 +27182,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -27259,14 +27261,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -27336,12 +27336,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -27413,14 +27415,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -27490,12 +27490,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -27567,14 +27569,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -31381,12 +31381,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -31458,14 +31460,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -31535,12 +31535,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -31612,14 +31614,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -31689,12 +31689,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -31766,14 +31768,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -31843,12 +31843,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -31920,14 +31922,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -34128,12 +34128,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -34205,14 +34207,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -34282,12 +34282,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -34359,14 +34361,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -34436,12 +34436,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -34513,14 +34515,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -34590,12 +34590,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -34667,14 +34669,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -36296,12 +36296,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -36373,14 +36375,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -36450,12 +36450,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -36527,14 +36529,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -36604,12 +36604,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -36681,14 +36683,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -36758,12 +36758,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -36835,14 +36837,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -38942,12 +38942,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -39019,14 +39021,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -39096,12 +39096,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -39173,14 +39175,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -39250,12 +39250,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -39327,14 +39329,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -39404,12 +39404,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -39481,14 +39483,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -43342,12 +43342,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -43419,14 +43421,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -43496,12 +43496,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -43573,14 +43575,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -43650,12 +43650,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -43727,14 +43729,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -43804,12 +43804,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -43881,14 +43883,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -47294,12 +47294,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -47371,14 +47373,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -47448,12 +47448,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -47525,14 +47527,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -47602,12 +47602,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -47679,14 +47681,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -47756,12 +47756,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -47833,14 +47835,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -52793,12 +52793,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -52870,14 +52872,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -52947,12 +52947,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -53024,14 +53026,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -53101,12 +53101,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -53178,14 +53180,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } @@ -53255,12 +53255,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zval *property_val; + zend_property_info *prop_info; if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: property_val = OBJ_PROP(zobj, prop_offset); if (Z_TYPE_P(property_val) != IS_UNDEF) { - zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); - if (prop_info != NULL) { value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); goto free_and_exit_assign_obj; @@ -53332,14 +53334,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } else { ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { - zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); - property_val = OBJ_PROP(zobj, prop_info->offset); - if (ZEND_TYPE_IS_SET(prop_info->type)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; - } else { - goto fast_assign_obj; + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; } + goto assign_obj_simple; } /* Fall through to write_property for hooks. */ } From 8254e8de31e7798e66c1f4537fe518677502ea7d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 7 Mar 2025 23:30:45 +0100 Subject: [PATCH 047/503] Fix lazy proxy calling set hook twice Writing to an uninitialized lazy proxy will initialize the underlying object and then call zend_std_write_property() on it. If this happens inside a hook, zend_std_write_property() should not call the hook again but directly write to the property slot. This didn't previously work because zend_should_call_hook() would compare the parent frame containing the proxy to the underlying object. This is now handled explicitly. Fixes GH-18000 Closes GH-18001 --- NEWS | 2 ++ Zend/tests/property_hooks/gh18000.phpt | 33 ++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 20 +++++++++++++--- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/property_hooks/gh18000.phpt diff --git a/NEWS b/NEWS index 87c99560ec350..0ba759b4de8d0 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS get_object_vars()). (ilutov) . Fixed bug GH-17998 (Skipped lazy object initialization on primed SIMPLE_WRITE cache). (ilutov) + . Fixed bug GH-17998 (Assignment to backing value in set hook of lazy proxy + calls hook again). (ilutov) - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) diff --git a/Zend/tests/property_hooks/gh18000.phpt b/Zend/tests/property_hooks/gh18000.phpt new file mode 100644 index 0000000000000..61b36034671f9 --- /dev/null +++ b/Zend/tests/property_hooks/gh18000.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-18000: Lazy proxy calls set hook twice +--FILE-- +prop = $value * 2; + } + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +function foo(C $c) { + $c->prop = 1; + var_dump($c->prop); +} + +foo($obj); + +?> +--EXPECT-- +set +init +int(2) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index bba40c6bd41ec..a4dba771e3ef5 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -673,9 +673,23 @@ static bool zend_is_in_hook(const zend_property_info *prop_info) static bool zend_should_call_hook(const zend_property_info *prop_info, const zend_object *obj) { - return !zend_is_in_hook(prop_info) - /* execute_data and This are guaranteed to be set if zend_is_in_hook() returns true. */ - || Z_OBJ(EG(current_execute_data)->This) != obj; + if (!zend_is_in_hook(prop_info)) { + return true; + } + + /* execute_data and This are guaranteed to be set if zend_is_in_hook() returns true. */ + zend_object *parent_obj = Z_OBJ(EG(current_execute_data)->This); + if (parent_obj == obj) { + return false; + } + + if (zend_object_is_lazy_proxy(parent_obj) + && zend_lazy_object_initialized(parent_obj) + && zend_lazy_object_get_instance(parent_obj) == obj) { + return false; + } + + return true; } static ZEND_COLD void zend_throw_no_prop_backing_value_access(zend_string *class_name, zend_string *prop_name, bool is_read) From b0858427aaccdae0db6764c0e86ae9489a92032e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 24 Mar 2023 10:13:25 +0100 Subject: [PATCH 048/503] Suppress snmp lib memory leak, skip ASAN tests I don't know enough about this library to fix those :( Cherry-picked from: be4db6b5505fb32489a5bf2723ea85b7af8d4fac ba1d9d0ab2cfae4c438513b7016c40b843868ac0 --- .github/lsan-suppressions.txt | 1 + ext/snmp/tests/snmp-object-errno-errstr.phpt | 1 + ext/snmp/tests/snmp-object-error.phpt | 1 + ext/snmp/tests/snmp2_get.phpt | 1 + ext/snmp/tests/snmp2_set-nomib.phpt | 1 + ext/snmp/tests/snmp2_walk.phpt | 1 + ext/snmp/tests/snmp3-error.phpt | 1 + ext/snmp/tests/snmp_getvalue.phpt | 1 + ext/snmp/tests/snmpget.phpt | 1 + ext/snmp/tests/snmpset-nomib.phpt | 1 + ext/snmp/tests/snmpwalk.phpt | 1 + 11 files changed, 11 insertions(+) diff --git a/.github/lsan-suppressions.txt b/.github/lsan-suppressions.txt index 5c2ee76e4607a..f547205d985b9 100644 --- a/.github/lsan-suppressions.txt +++ b/.github/lsan-suppressions.txt @@ -1 +1,2 @@ leak:acommon::DictInfoList::elements +leak:netsnmp_init_mib_internals diff --git a/ext/snmp/tests/snmp-object-errno-errstr.phpt b/ext/snmp/tests/snmp-object-errno-errstr.phpt index 831a9f3319dbb..783191c2c00d8 100644 --- a/ext/snmp/tests/snmp-object-errno-errstr.phpt +++ b/ext/snmp/tests/snmp-object-errno-errstr.phpt @@ -7,6 +7,7 @@ snmp --SKIPIF-- --FILE-- --FILE-- --FILE-- --ENV-- MIBS= diff --git a/ext/snmp/tests/snmp2_walk.phpt b/ext/snmp/tests/snmp2_walk.phpt index 4cd9b3a85b6fd..fcf14424ca057 100644 --- a/ext/snmp/tests/snmp2_walk.phpt +++ b/ext/snmp/tests/snmp2_walk.phpt @@ -7,6 +7,7 @@ snmp --SKIPIF-- --FILE-- --FILE-- --FILE-- --FILE-- --ENV-- MIBS= diff --git a/ext/snmp/tests/snmpwalk.phpt b/ext/snmp/tests/snmpwalk.phpt index b0e8a8a8afd18..61ef33a70a292 100644 --- a/ext/snmp/tests/snmpwalk.phpt +++ b/ext/snmp/tests/snmpwalk.phpt @@ -7,6 +7,7 @@ snmp --SKIPIF-- --FILE-- Date: Fri, 7 Mar 2025 17:56:17 +0100 Subject: [PATCH 049/503] Fix GH-17989: mb_output_handler crash with unset http_output_conv_mimetypes The INI option can be NULL or invalid, resulting in a NULL global. So we have to add a NULL check. Closes GH-17996. --- NEWS | 4 ++++ ext/mbstring/mbstring.c | 4 +++- ext/mbstring/tests/gh17989.phpt | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 ext/mbstring/tests/gh17989.phpt diff --git a/NEWS b/NEWS index 46b0934b8700e..02b02bb84bdc0 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) +- Mbstring: + . Fixed bug GH-17989 (mb_output_handler crash with unset + http_output_conv_mimetypes). (nielsdos) + - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index dbf012174c494..dec565707fa78 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -1567,7 +1567,9 @@ PHP_FUNCTION(mb_output_handler) char *mimetype = NULL; /* Analyze mime type */ - if (SG(sapi_headers).mimetype && _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) { + if (SG(sapi_headers).mimetype + && MBSTRG(http_output_conv_mimetypes) + && _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) { char *s; if ((s = strchr(SG(sapi_headers).mimetype, ';')) == NULL) { mimetype = estrdup(SG(sapi_headers).mimetype); diff --git a/ext/mbstring/tests/gh17989.phpt b/ext/mbstring/tests/gh17989.phpt new file mode 100644 index 0000000000000..40efd5866c171 --- /dev/null +++ b/ext/mbstring/tests/gh17989.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes) +--EXTENSIONS-- +mbstring +--INI-- +mbstring.http_output_conv_mimetypes= +--FILE-- + +--EXPECT-- +set mime type via this echo +hi From 9be9f70caab7e58141d1be145d23cf39d676be0b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 8 Mar 2025 19:38:42 +0100 Subject: [PATCH 050/503] Fix weird unpack behaviour in DOM Engine pitfall: the iter index is only updated by foreach opcodes, so the existing code that used it as an index for the nodes w.r.t. the start did not work properly. Fix it by using our own counter. Closes GH-18004. --- NEWS | 3 ++ ext/dom/dom_iterators.c | 12 ++++---- ext/dom/php_dom.h | 3 ++ ext/dom/tests/unpack_foreach_behaviour.phpt | 31 +++++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 ext/dom/tests/unpack_foreach_behaviour.phpt diff --git a/NEWS b/NEWS index 02b02bb84bdc0..c3156e8ce4e40 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.19 +- DOM: + . Fix weird unpack behaviour in DOM. (nielsdos) + - GD: . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index ff63342595ae9..c8256de239d93 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -158,7 +158,7 @@ static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key) zval *object = &iterator->intern.data; if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry)) { - ZVAL_LONG(key, iter->index); + ZVAL_LONG(key, iterator->index); } else { dom_object *intern = Z_DOMOBJ_P(&iterator->curobj); @@ -189,6 +189,8 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */ return; } + iterator->index++; + intern = Z_DOMOBJ_P(&iterator->curobj); object = &iterator->intern.data; nnmap = Z_DOMOBJ_P(object); @@ -227,18 +229,18 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */ curnode = basenode->children; } } else { - previndex = iter->index - 1; + previndex = iterator->index - 1; curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; } curnode = dom_get_elements_by_tag_name_ns_raw( - basenode, curnode, (char *) objmap->ns, (char *) objmap->local, &previndex, iter->index); + basenode, curnode, (char *) objmap->ns, (char *) objmap->local, &previndex, iterator->index); } } } else { if (objmap->nodetype == XML_ENTITY_NODE) { - curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index); + curnode = php_dom_libxml_hash_iter(objmap->ht, iterator->index); } else { - curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index); + curnode = php_dom_libxml_notation_iter(objmap->ht, iterator->index); } } } diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 2bccb2d5692d5..120af4267658c 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -98,6 +98,9 @@ typedef struct { zend_object_iterator intern; zval curobj; HashPosition pos; + /* intern->index is only updated for FE_* opcodes, not for e.g. unpacking, + * yet we need to track the position of the node relative to the start. */ + zend_ulong index; php_libxml_cache_tag cache_tag; } php_dom_iterator; diff --git a/ext/dom/tests/unpack_foreach_behaviour.phpt b/ext/dom/tests/unpack_foreach_behaviour.phpt new file mode 100644 index 0000000000000..42fe896d9f786 --- /dev/null +++ b/ext/dom/tests/unpack_foreach_behaviour.phpt @@ -0,0 +1,31 @@ +--TEST-- +Unpacking vs foreach behaviour +--EXTENSIONS-- +dom +--FILE-- +loadXML(''); + +echo "--- By foreach: ---\n"; + +foreach ($dom->documentElement->getElementsByTagName('*') as $node) { + var_dump($node->localName); +} + +echo "--- By unpacking: ---\n"; + +$iter = $dom->documentElement->getElementsByTagName('*'); +foreach ([...$iter] as $node) { + var_dump($node->localName); +} + +?> +--EXPECT-- +--- By foreach: --- +string(1) "a" +string(1) "b" +--- By unpacking: --- +string(1) "a" +string(1) "b" From d6172ce37ae37e1d5a54db6b3cdffb78b2ca99d1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 10 Mar 2025 11:24:20 +0100 Subject: [PATCH 051/503] [skip ci] Ignore snmp test on asan that frequently times out Not sure why this happens only on master. Cherry-picked from becf207d0c59a48b737d5a177a83f5b233f9bfa0 No longer happens just on master. ;) --- ext/snmp/tests/gh16959.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/snmp/tests/gh16959.phpt b/ext/snmp/tests/gh16959.phpt index ce647b15b9dac..cabe0eb84b6cb 100644 --- a/ext/snmp/tests/gh16959.phpt +++ b/ext/snmp/tests/gh16959.phpt @@ -5,6 +5,7 @@ snmp --SKIPIF-- --FILE-- Date: Sat, 8 Mar 2025 15:21:18 +0100 Subject: [PATCH 052/503] Increase CircleCI no_output_timeout Closes GH-18002 --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d9ad3f7c0a658..b440bd643e6f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -166,6 +166,7 @@ jobs: `#--enable-werror` - run: name: make + no_output_timeout: 30m command: make -j2 > /dev/null - run: name: make install @@ -177,6 +178,7 @@ jobs: echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini - run: name: Test + no_output_timeout: 30m command: | sapi/cli/php run-tests.php \ -d zend_extension=opcache.so \ From f209eb448e765fd920ab79c0abaf083ea275529b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 10 Mar 2025 20:22:11 +0100 Subject: [PATCH 053/503] Fix tests for libxml2 2.14 See GH-18009. --- ext/dom/tests/DOMDocument_loadHTMLfile_variation1.phpt | 4 ++++ ext/dom/tests/bug69679.phpt | 4 ++-- ext/dom/tests/bug78025.phpt | 3 +-- ext/dom/tests/bug80268_2.phpt | 7 ++----- ext/simplexml/tests/bug51615.phpt | 7 ++----- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ext/dom/tests/DOMDocument_loadHTMLfile_variation1.phpt b/ext/dom/tests/DOMDocument_loadHTMLfile_variation1.phpt index 3519a9fa215f4..f6ebd25761b06 100644 --- a/ext/dom/tests/DOMDocument_loadHTMLfile_variation1.phpt +++ b/ext/dom/tests/DOMDocument_loadHTMLfile_variation1.phpt @@ -8,6 +8,10 @@ Antonio Diaz Ruiz assert.bail=true --EXTENSIONS-- dom +--SKIPIF-- += 21400) die("skip libxml >= 2.14 no longer has this non-standard warning"); +?> --FILE-- U+0000 loadHTML($html); print($doc->saveHTML()); ?> ---EXPECT-- +--EXPECTF-- -U+0000 +U+0000 %r(�|)%r diff --git a/ext/dom/tests/bug78025.phpt b/ext/dom/tests/bug78025.phpt index 910f7728c3c2c..d6f84939c5f14 100644 --- a/ext/dom/tests/bug78025.phpt +++ b/ext/dom/tests/bug78025.phpt @@ -6,9 +6,8 @@ dom "; $dom = new DOMDocument; -$dom->loadHTML($htm); +$dom->loadHTML($htm, LIBXML_NOERROR); var_dump($dom->doctype->name); ?> --EXPECTF-- -Warning: DOMDocument::loadHTML(): htmlParseDocTypeDecl : no DOCTYPE name ! in Entity, line: 1 in %s on line %d string(0) "" diff --git a/ext/dom/tests/bug80268_2.phpt b/ext/dom/tests/bug80268_2.phpt index af8cf7faca5a5..dcde29e6835a7 100644 --- a/ext/dom/tests/bug80268_2.phpt +++ b/ext/dom/tests/bug80268_2.phpt @@ -9,13 +9,13 @@ if (LIBXML_VERSION < 20912) die('skip For libxml2 >= 2.9.12 only'); --FILE-- loadHTML("

foo\0bar

"); +$doc->loadHTML("

foo\0bar

", LIBXML_NOERROR); $html = $doc->saveHTML(); var_dump(strpos($html, '

foo

') !== false); file_put_contents(__DIR__ . '/80268.html', "

foo\0bar

"); $doc = new DOMDocument; -$doc->loadHTMLFile(__DIR__ . '/80268.html'); +$doc->loadHTMLFile(__DIR__ . '/80268.html', LIBXML_NOERROR); $html = $doc->saveHTML(); var_dump(strpos($html, '

foo

') !== false); ?> @@ -24,8 +24,5 @@ var_dump(strpos($html, '

foo

') !== false); unlink(__DIR__ . '/80268.html'); ?> --EXPECTF-- -Warning: DOMDocument::loadHTML(): Char 0x0 out of allowed range in Entity, line: 1 in %s on line %d bool(false) - -Warning: DOMDocument::loadHTMLFile(): Char 0x0 out of allowed range in %s on line %d bool(false) diff --git a/ext/simplexml/tests/bug51615.phpt b/ext/simplexml/tests/bug51615.phpt index b0ac921fead2a..7245434ff5578 100644 --- a/ext/simplexml/tests/bug51615.phpt +++ b/ext/simplexml/tests/bug51615.phpt @@ -7,7 +7,7 @@ dom loadHTML('xx'); +$dom->loadHTML('xx', LIBXML_NOERROR); $html = simplexml_import_dom($dom); var_dump($html->body->span); @@ -18,15 +18,12 @@ foreach ($html->body->span as $obj) { ?> --EXPECTF-- -Warning: DOMDocument::loadHTML(): error parsing attribute name in Entity, line: 1 in %s on line %d - -Warning: DOMDocument::loadHTML(): error parsing attribute name in Entity, line: 1 in %s on line %d object(SimpleXMLElement)#%d (3) { ["@attributes"]=> array(2) { ["title"]=> string(0) "" - ["y"]=> + [%r("y"{1,2})%r]=> string(0) "" } [0]=> From b5471300d2acc2499408351521cf3a182114466c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 10 Mar 2025 20:23:23 +0100 Subject: [PATCH 054/503] Fix test GH-16535 for libxml2 2.14 --- ext/dom/tests/gh16535.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/dom/tests/gh16535.phpt b/ext/dom/tests/gh16535.phpt index 1c8d282303c88..adb1dfa91f204 100644 --- a/ext/dom/tests/gh16535.phpt +++ b/ext/dom/tests/gh16535.phpt @@ -14,7 +14,7 @@ try { } catch (DOMException $e) { echo $e->getMessage(), "\n"; } -$v2->loadHTML("oU"); +$v2->loadHTML("

oU

"); echo $v2->saveXML(); ?> From 4ca6bde32fcb3d32e57b7a976189a7bd0954a941 Mon Sep 17 00:00:00 2001 From: Christian Schneider Date: Tue, 11 Mar 2025 12:08:53 +0100 Subject: [PATCH 055/503] Fix bug and add test for dba_open same file twice (#17979) Co-authored-by: Christian Schneider --- ext/dba/dba.c | 3 ++- ext/dba/tests/dba_duplicateopen.phpt | 34 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 ext/dba/tests/dba_duplicateopen.phpt diff --git a/ext/dba/dba.c b/ext/dba/dba.c index e4986e1cd2321..2205b13dfe050 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -57,6 +57,7 @@ ZEND_BEGIN_MODULE_GLOBALS(dba) const char *default_handler; const dba_handler *default_hptr; HashTable connections; + unsigned int connection_counter; ZEND_END_MODULE_GLOBALS(dba) ZEND_DECLARE_MODULE_GLOBALS(dba) @@ -571,7 +572,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) char *resource_key; size_t resource_key_len = spprintf(&resource_key, 0, - "dba_%d_%s_%s_%s", persistent, ZSTR_VAL(path), ZSTR_VAL(mode), handler_str ? ZSTR_VAL(handler_str) : "" + "dba_%d_%u_%s_%s_%s", persistent, persistent ? 0 : DBA_G(connection_counter)++, ZSTR_VAL(path), ZSTR_VAL(mode), handler_str ? ZSTR_VAL(handler_str) : "" ); if (persistent) { diff --git a/ext/dba/tests/dba_duplicateopen.phpt b/ext/dba/tests/dba_duplicateopen.phpt new file mode 100644 index 0000000000000..7068981f1a3c8 --- /dev/null +++ b/ext/dba/tests/dba_duplicateopen.phpt @@ -0,0 +1,34 @@ +--TEST-- +DBA open same read only file multiple times +--EXTENSIONS-- +dba +--SKIPIF-- + +--CONFLICTS-- +test.cdb +--FILE-- + +--EXPECT-- +database handler: cdb +1122 From bb4174e6bcb72d781d2438a4b7e946ee6e2590b9 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 11 Mar 2025 11:10:19 +0000 Subject: [PATCH 056/503] [skip ci] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 88b34353d5ae2..9a356c3c637b6 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug GH-17998 (Assignment to backing value in set hook of lazy proxy calls hook again). (ilutov) +- DBA: + . Fixed assertion violation when opening the same file with dba_open + multiple times. (chschneider) + - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) . Fix weird unpack behaviour in DOM. (nielsdos) From 175b962f554b00c5797ce4691832eb0d00ed7370 Mon Sep 17 00:00:00 2001 From: Eric Mann Date: Tue, 11 Mar 2025 12:06:18 -0700 Subject: [PATCH 057/503] Fix NEWS versions for posterity --- NEWS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index c3156e8ce4e40..f8f13f016bc88 100644 --- a/NEWS +++ b/NEWS @@ -16,7 +16,7 @@ PHP NEWS - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) -27 Feb 2025, PHP 8.3.18RC1 +27 Feb 2025, PHP 8.3.18 - BCMath: . Fixed bug GH-17398 (bcmul memory leak). (SakiTakamachi) @@ -177,7 +177,7 @@ PHP NEWS . Fixed bug GH-17139 (Fix zip_entry_name() crash on invalid entry). (nielsdos) -02 Jan 2025, PHP 8.3.16RC1 +02 Jan 2025, PHP 8.3.16 - Core: . Fixed bug GH-17106 (ZEND_MATCH_ERROR misoptimization). (ilutov) @@ -376,7 +376,7 @@ PHP NEWS - Windows: . Fixed bug GH-16849 (Error dialog causes process to hang). (cmb) -07 Nov 2024, PHP 8.3.14RC1 +07 Nov 2024, PHP 8.3.14 - CLI: . Fixed bug GH-16373 (Shebang is not skipped for router script in cli-server @@ -1129,7 +1129,7 @@ PHP NEWS - Treewide: . Fix gcc-14 Wcalloc-transposed-args warnings. (Cristian Rodríguez) -28 Mar 2024, PHP 8.3.5RC1 +28 Mar 2024, PHP 8.3.5 - Core: . Fixed GH-13569 (GC buffer unnecessarily grows up to GC_MAX_BUF_SIZE when @@ -1398,7 +1398,7 @@ PHP NEWS . Fixed bug GH-12980 (tidynode.props.attribute is missing "Boolean Attributes" and empty attributes). (nielsdos) -07 Dec 2023, PHP 8.3.1RC1 +07 Dec 2023, PHP 8.3.1 - Core: . Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within From 21fd08be71185f1525709fd76aeccfa59fd7056e Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 11 Mar 2025 20:03:28 +0000 Subject: [PATCH 058/503] ext/sockets: adding SO_BUSY_POLL socket option for Linux. (#17954) To possibly reduce the latency when polling packets by activating it from the network interface for N microseconds. The kernel by doing so, increase the CPU(s) activity bound to the socket significantly. Note that not only the kernel needs to have support enabled for it (which the average distribution usually does) but the network interface itself needs to support it too. If not, it is just a no-op. --- NEWS | 1 + UPGRADING | 1 + ext/sockets/sockets.stub.php | 7 +++++++ ext/sockets/sockets_arginfo.h | 5 ++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 68e7df9d84f7f..18e1f76dabe2c 100644 --- a/NEWS +++ b/NEWS @@ -150,6 +150,7 @@ PHP NEWS . socket_getsockname/socket_create/socket_bind handled AF_PACKET family socket. (David Carlier) . Added IP_BINDANY for a socket to bind to any address. (David Carlier) + . Added SO_BUSY_POOL to reduce packets poll latency. (David Carlier) - Sodium: . Fix overall theorical overflows on zend_string buffer allocations. diff --git a/UPGRADING b/UPGRADING index 21cf4d3062df7..5d372c72e2139 100644 --- a/UPGRADING +++ b/UPGRADING @@ -308,6 +308,7 @@ PHP 8.5 UPGRADE NOTES . TCP_BBR_ALGORITHM (FreeBSD only). . AF_PACKET (Linux only). . IP_BINDANY (FreeBSD/NetBSD/OpenBSD only). + . SO_BUSY_POLL (Linux only). ======================================== 11. Changes to INI File Handling diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 4d6200fcd1ffe..d647f46b80dca 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -454,6 +454,13 @@ */ const SO_EXCLBIND = UNKNOWN; #endif +#ifdef SO_BUSY_POLL +/** + * @var int + * @cvalue SO_BUSY_POLL + */ +const SO_BUSY_POLL = UNKNOWN; +#endif #ifdef SKF_AD_OFF /** * @var int diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 4a90b4d789feb..45714fb285174 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: aac197335037777d31d83d4a4040bbfcd0c55813 */ + * Stub hash: 42d486d2666d23569e70860e2b1ef203161792b3 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1) @@ -476,6 +476,9 @@ static void register_sockets_symbols(int module_number) #if defined(SO_EXCLBIND) REGISTER_LONG_CONSTANT("SO_EXCLBIND", SO_EXCLBIND, CONST_PERSISTENT); #endif +#if defined(SO_BUSY_POLL) + REGISTER_LONG_CONSTANT("SO_BUSY_POLL", SO_BUSY_POLL, CONST_PERSISTENT); +#endif #if defined(SKF_AD_OFF) REGISTER_LONG_CONSTANT("SKF_AD_OFF", SKF_AD_OFF, CONST_PERSISTENT); #endif From d20b4c97a9f883b62b65b82d939c5af9a2028ef1 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 31 Dec 2024 18:57:02 +0100 Subject: [PATCH 059/503] Fix GHSA-ghsa-v8xr-gpvj-cx9g: http header folding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds HTTP header folding support for HTTP wrapper response headers. Reviewed-by: Tim Düsterhus --- ext/standard/http_fopen_wrapper.c | 343 ++++++++++++------ .../tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt | 49 +++ .../tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt | 51 +++ .../tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt | 49 +++ .../tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt | 48 +++ .../tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt | 48 +++ .../tests/http/http_response_header_05.phpt | 30 -- 7 files changed, 484 insertions(+), 134 deletions(-) create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt delete mode 100644 ext/standard/tests/http/http_response_header_05.phpt diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 0a1cf0c5bf046..66f356222b4e0 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -115,6 +115,171 @@ static bool check_has_header(const char *headers, const char *header) { return 0; } +typedef struct _php_stream_http_response_header_info { + php_stream_filter *transfer_encoding; + size_t file_size; + bool follow_location; + char location[HTTP_HEADER_BLOCK_SIZE]; +} php_stream_http_response_header_info; + +static void php_stream_http_response_header_info_init( + php_stream_http_response_header_info *header_info) +{ + header_info->transfer_encoding = NULL; + header_info->file_size = 0; + header_info->follow_location = 1; + header_info->location[0] = '\0'; +} + +/* Trim white spaces from response header line and update its length */ +static bool php_stream_http_response_header_trim(char *http_header_line, + size_t *http_header_line_length) +{ + char *http_header_line_end = http_header_line + *http_header_line_length - 1; + while (http_header_line_end >= http_header_line && + (*http_header_line_end == '\n' || *http_header_line_end == '\r')) { + http_header_line_end--; + } + + /* The primary definition of an HTTP header in RFC 7230 states: + * > Each header field consists of a case-insensitive field name followed + * > by a colon (":"), optional leading whitespace, the field value, and + * > optional trailing whitespace. */ + + /* Strip trailing whitespace */ + bool space_trim = (*http_header_line_end == ' ' || *http_header_line_end == '\t'); + if (space_trim) { + do { + http_header_line_end--; + } while (http_header_line_end >= http_header_line && + (*http_header_line_end == ' ' || *http_header_line_end == '\t')); + } + http_header_line_end++; + *http_header_line_end = '\0'; + *http_header_line_length = http_header_line_end - http_header_line; + + return space_trim; +} + +/* Process folding headers of the current line and if there are none, parse last full response + * header line. It returns NULL if the last header is finished, otherwise it returns updated + * last header line. */ +static zend_string *php_stream_http_response_headers_parse(php_stream *stream, + php_stream_context *context, int options, zend_string *last_header_line_str, + char *header_line, size_t *header_line_length, int response_code, + zval *response_header, php_stream_http_response_header_info *header_info) +{ + char *last_header_line = ZSTR_VAL(last_header_line_str); + size_t last_header_line_length = ZSTR_LEN(last_header_line_str); + char *last_header_line_end = ZSTR_VAL(last_header_line_str) + ZSTR_LEN(last_header_line_str) - 1; + + /* Process non empty header line. */ + if (header_line && (*header_line != '\n' && *header_line != '\r')) { + /* Removing trailing white spaces. */ + if (php_stream_http_response_header_trim(header_line, header_line_length) && + *header_line_length == 0) { + /* Only spaces so treat as an empty folding header. */ + return last_header_line_str; + } + + /* Process folding headers if starting with a space or a tab. */ + if (header_line && (*header_line == ' ' || *header_line == '\t')) { + char *http_folded_header_line = header_line; + size_t http_folded_header_line_length = *header_line_length; + /* Remove the leading white spaces. */ + while (*http_folded_header_line == ' ' || *http_folded_header_line == '\t') { + http_folded_header_line++; + http_folded_header_line_length--; + } + /* It has to have some characters because it would get returned after the call + * php_stream_http_response_header_trim above. */ + ZEND_ASSERT(http_folded_header_line_length > 0); + /* Concatenate last header line, space and current header line. */ + zend_string *extended_header_str = zend_string_concat3( + last_header_line, last_header_line_length, + " ", 1, + http_folded_header_line, http_folded_header_line_length); + zend_string_efree(last_header_line_str); + last_header_line_str = extended_header_str; + /* Return new header line. */ + return last_header_line_str; + } + } + + /* Find header separator position. */ + char *last_header_value = memchr(last_header_line, ':', last_header_line_length); + if (last_header_value) { + last_header_value++; /* Skip ':'. */ + + /* Strip leading whitespace. */ + while (last_header_value < last_header_line_end + && (*last_header_value == ' ' || *last_header_value == '\t')) { + last_header_value++; + } + } else { + /* There is no colon. Set the value to the end of the header line, which is effectively + * an empty string. */ + last_header_value = last_header_line_end; + } + + bool store_header = true; + zval *tmpzval = NULL; + + if (!strncasecmp(last_header_line, "Location:", sizeof("Location:")-1)) { + /* Check if the location should be followed. */ + if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) { + header_info->follow_location = zval_is_true(tmpzval); + } else if (!((response_code >= 300 && response_code < 304) + || 307 == response_code || 308 == response_code)) { + /* The redirection should not be automatic if follow_location is not set and + * response_code not in (300, 301, 302, 303 and 307) + * see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1 + * RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */ + header_info->follow_location = 0; + } + strlcpy(header_info->location, last_header_value, sizeof(header_info->location)); + } else if (!strncasecmp(last_header_line, "Content-Type:", sizeof("Content-Type:")-1)) { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, last_header_value, 0); + } else if (!strncasecmp(last_header_line, "Content-Length:", sizeof("Content-Length:")-1)) { + header_info->file_size = atoi(last_header_value); + php_stream_notify_file_size(context, header_info->file_size, last_header_line, 0); + } else if ( + !strncasecmp(last_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1) + && !strncasecmp(last_header_value, "Chunked", sizeof("Chunked")-1) + ) { + /* Create filter to decode response body. */ + if (!(options & STREAM_ONLY_GET_HEADERS)) { + zend_long decode = 1; + + if (context && (tmpzval = php_stream_context_get_option(context, "http", "auto_decode")) != NULL) { + decode = zend_is_true(tmpzval); + } + if (decode) { + if (header_info->transfer_encoding != NULL) { + /* Prevent a memory leak in case there are more transfer-encoding headers. */ + php_stream_filter_free(header_info->transfer_encoding); + } + header_info->transfer_encoding = php_stream_filter_create( + "dechunk", NULL, php_stream_is_persistent(stream)); + if (header_info->transfer_encoding != NULL) { + /* Do not store transfer-encoding header. */ + store_header = false; + } + } + } + } + + if (store_header) { + zval http_header; + ZVAL_NEW_STR(&http_header, last_header_line_str); + zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header); + } else { + zend_string_efree(last_header_line_str); + } + + return NULL; +} + static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context, int redirect_max, int flags, @@ -127,11 +292,12 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, zend_string *tmp = NULL; char *ua_str = NULL; zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name; - char location[HTTP_HEADER_BLOCK_SIZE]; int reqok = 0; char *http_header_line = NULL; + zend_string *last_header_line_str = NULL; + php_stream_http_response_header_info header_info; char tmp_line[128]; - size_t chunk_size = 0, file_size = 0; + size_t chunk_size = 0; int eol_detect = 0; zend_string *transport_string; zend_string *errstr = NULL; @@ -142,8 +308,6 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0); int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0); int redirect_keep_method = ((flags & HTTP_WRAPPER_KEEP_METHOD) != 0); - bool follow_location = 1; - php_stream_filter *transfer_encoding = NULL; int response_code; smart_str req_buf = {0}; bool custom_request_method; @@ -653,8 +817,6 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* send it */ php_stream_write(stream, ZSTR_VAL(req_buf.s), ZSTR_LEN(req_buf.s)); - location[0] = '\0'; - if (Z_ISUNDEF_P(response_header)) { array_init(response_header); } @@ -736,130 +898,101 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, } } - /* read past HTTP headers */ + php_stream_http_response_header_info_init(&header_info); + /* read past HTTP headers */ while (!php_stream_eof(stream)) { size_t http_header_line_length; if (http_header_line != NULL) { efree(http_header_line); } - if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') { - char *e = http_header_line + http_header_line_length - 1; - char *http_header_value; - - while (e >= http_header_line && (*e == '\n' || *e == '\r')) { - e--; - } - - /* The primary definition of an HTTP header in RFC 7230 states: - * > Each header field consists of a case-insensitive field name followed - * > by a colon (":"), optional leading whitespace, the field value, and - * > optional trailing whitespace. */ - - /* Strip trailing whitespace */ - while (e >= http_header_line && (*e == ' ' || *e == '\t')) { - e--; - } - - /* Terminate header line */ - e++; - *e = '\0'; - http_header_line_length = e - http_header_line; - - http_header_value = memchr(http_header_line, ':', http_header_line_length); - if (http_header_value) { - http_header_value++; /* Skip ':' */ - - /* Strip leading whitespace */ - while (http_header_value < e - && (*http_header_value == ' ' || *http_header_value == '\t')) { - http_header_value++; + if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length))) { + bool last_line; + if (*http_header_line == '\r') { + if (http_header_line[1] != '\n') { + php_stream_close(stream); + stream = NULL; + php_stream_wrapper_log_error(wrapper, options, + "HTTP invalid header name (cannot start with CR character)!"); + goto out; } + last_line = true; + } else if (*http_header_line == '\n') { + last_line = true; } else { - /* There is no colon. Set the value to the end of the header line, which is - * effectively an empty string. */ - http_header_value = e; + last_line = false; } - - if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) { - if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) { - follow_location = zval_is_true(tmpzval); - } else if (!((response_code >= 300 && response_code < 304) - || 307 == response_code || 308 == response_code)) { - /* we shouldn't redirect automatically - if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307) - see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1 - RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */ - follow_location = 0; + + if (last_header_line_str != NULL) { + /* Parse last header line. */ + last_header_line_str = php_stream_http_response_headers_parse(stream, context, + options, last_header_line_str, http_header_line, &http_header_line_length, + response_code, response_header, &header_info); + if (last_header_line_str != NULL) { + /* Folding header present so continue. */ + continue; } - strlcpy(location, http_header_value, sizeof(location)); - } else if (!strncasecmp(http_header_line, "Content-Type:", sizeof("Content-Type:")-1)) { - php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_value, 0); - } else if (!strncasecmp(http_header_line, "Content-Length:", sizeof("Content-Length:")-1)) { - file_size = atoi(http_header_value); - php_stream_notify_file_size(context, file_size, http_header_line, 0); - } else if ( - !strncasecmp(http_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1) - && !strncasecmp(http_header_value, "Chunked", sizeof("Chunked")-1) - ) { - - /* create filter to decode response body */ - if (!(options & STREAM_ONLY_GET_HEADERS)) { - zend_long decode = 1; - - if (context && (tmpzval = php_stream_context_get_option(context, "http", "auto_decode")) != NULL) { - decode = zend_is_true(tmpzval); - } - if (decode) { - transfer_encoding = php_stream_filter_create("dechunk", NULL, php_stream_is_persistent(stream)); - if (transfer_encoding) { - /* don't store transfer-encodeing header */ - continue; - } - } + } else if (!last_line) { + /* The first line cannot start with spaces. */ + if (*http_header_line == ' ' || *http_header_line == '\t') { + php_stream_close(stream); + stream = NULL; + php_stream_wrapper_log_error(wrapper, options, + "HTTP invalid response format (folding header at the start)!"); + goto out; } + /* Trim the first line if it is not the last line. */ + php_stream_http_response_header_trim(http_header_line, &http_header_line_length); } - - { - zval http_header; - ZVAL_STRINGL(&http_header, http_header_line, http_header_line_length); - zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header); + if (last_line) { + /* For the last line the last header line must be NULL. */ + ZEND_ASSERT(last_header_line_str == NULL); + break; } + /* Save current line as the last line so it gets parsed in the next round. */ + last_header_line_str = zend_string_init(http_header_line, http_header_line_length, 0); } else { break; } } - if (!reqok || (location[0] != '\0' && follow_location)) { - if (!follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) { + /* If the stream was closed early, we still want to process the last line to keep BC. */ + if (last_header_line_str != NULL) { + php_stream_http_response_headers_parse(stream, context, options, last_header_line_str, + NULL, NULL, response_code, response_header, &header_info); + } + + if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) { + if (!header_info.follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) { goto out; } - if (location[0] != '\0') - php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0); + if (header_info.location[0] != '\0') + php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, header_info.location, 0); php_stream_close(stream); stream = NULL; - if (transfer_encoding) { - php_stream_filter_free(transfer_encoding); - transfer_encoding = NULL; + if (header_info.transfer_encoding) { + php_stream_filter_free(header_info.transfer_encoding); + header_info.transfer_encoding = NULL; } - if (location[0] != '\0') { + if (header_info.location[0] != '\0') { char new_path[HTTP_HEADER_BLOCK_SIZE]; char loc_path[HTTP_HEADER_BLOCK_SIZE]; *new_path='\0'; - if (strlen(location)<8 || (strncasecmp(location, "http://", sizeof("http://")-1) && - strncasecmp(location, "https://", sizeof("https://")-1) && - strncasecmp(location, "ftp://", sizeof("ftp://")-1) && - strncasecmp(location, "ftps://", sizeof("ftps://")-1))) + if (strlen(header_info.location) < 8 || + (strncasecmp(header_info.location, "http://", sizeof("http://")-1) && + strncasecmp(header_info.location, "https://", sizeof("https://")-1) && + strncasecmp(header_info.location, "ftp://", sizeof("ftp://")-1) && + strncasecmp(header_info.location, "ftps://", sizeof("ftps://")-1))) { - if (*location != '/') { - if (*(location+1) != '\0' && resource->path) { + if (*header_info.location != '/') { + if (*(header_info.location+1) != '\0' && resource->path) { char *s = strrchr(ZSTR_VAL(resource->path), '/'); if (!s) { s = ZSTR_VAL(resource->path); @@ -875,15 +1008,17 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (resource->path && ZSTR_VAL(resource->path)[0] == '/' && ZSTR_VAL(resource->path)[1] == '\0') { - snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", ZSTR_VAL(resource->path), location); + snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", + ZSTR_VAL(resource->path), header_info.location); } else { - snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", ZSTR_VAL(resource->path), location); + snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", + ZSTR_VAL(resource->path), header_info.location); } } else { - snprintf(loc_path, sizeof(loc_path) - 1, "/%s", location); + snprintf(loc_path, sizeof(loc_path) - 1, "/%s", header_info.location); } } else { - strlcpy(loc_path, location, sizeof(loc_path)); + strlcpy(loc_path, header_info.location, sizeof(loc_path)); } if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) { snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path); @@ -891,7 +1026,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), loc_path); } } else { - strlcpy(new_path, location, sizeof(new_path)); + strlcpy(new_path, header_info.location, sizeof(new_path)); } php_url_free(resource); @@ -951,7 +1086,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (header_init) { ZVAL_COPY(&stream->wrapperdata, response_header); } - php_stream_notify_progress_init(context, 0, file_size); + php_stream_notify_progress_init(context, 0, header_info.file_size); /* Restore original chunk size now that we're done with headers */ if (options & STREAM_WILL_CAST) @@ -967,8 +1102,8 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* restore mode */ strlcpy(stream->mode, mode, sizeof(stream->mode)); - if (transfer_encoding) { - php_stream_filter_append(&stream->readfilters, transfer_encoding); + if (header_info.transfer_encoding) { + php_stream_filter_append(&stream->readfilters, header_info.transfer_encoding); } /* It's possible that the server already sent in more data than just the headers. diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt new file mode 100644 index 0000000000000..f935b5a02ca94 --- /dev/null +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt @@ -0,0 +1,49 @@ +--TEST-- +GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (single) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\n charset=utf-8\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html; charset=utf-8 +string(4) "body" +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(38) "Content-Type: text/html; charset=utf-8" +} diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt new file mode 100644 index 0000000000000..078d605b6718f --- /dev/null +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt @@ -0,0 +1,51 @@ +--TEST-- +GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (multiple) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\nCustom-Header: somevalue;\r\n param1=value1; \r\n param2=value2\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html; +string(4) "body" +array(3) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(24) "Content-Type: text/html;" + [2]=> + string(54) "Custom-Header: somevalue; param1=value1; param2=value2" +} diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt new file mode 100644 index 0000000000000..ad5ddc879cead --- /dev/null +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt @@ -0,0 +1,49 @@ +--TEST-- +GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (empty) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\n \r\n charset=utf-8\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html; charset=utf-8 +string(4) "body" +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(38) "Content-Type: text/html; charset=utf-8" +} diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt new file mode 100644 index 0000000000000..d0396e819fbd3 --- /dev/null +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt @@ -0,0 +1,48 @@ +--TEST-- +GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (first line) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\n Content-Type: text/html;\r\n \r\n charset=utf-8\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (folding header at the start)! in %s +bool(false) +array(1) { + [0]=> + string(15) "HTTP/1.0 200 Ok" +} diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt new file mode 100644 index 0000000000000..037d2002cc537 --- /dev/null +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt @@ -0,0 +1,48 @@ +--TEST-- +GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (CR before header name) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\n\rIgnored: ignored\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid header name (cannot start with CR character)! in %s +bool(false) +array(1) { + [0]=> + string(15) "HTTP/1.0 200 Ok" +} diff --git a/ext/standard/tests/http/http_response_header_05.phpt b/ext/standard/tests/http/http_response_header_05.phpt deleted file mode 100644 index c5fe60fa612b7..0000000000000 --- a/ext/standard/tests/http/http_response_header_05.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -$http_reponse_header (whitespace-only "header") ---SKIPIF-- - ---INI-- -allow_url_fopen=1 ---FILE-- - $pid, 'uri' => $uri] = http_server($responses, $output); - -$f = file_get_contents($uri); -var_dump($f); -var_dump($http_response_header); - -http_server_kill($pid); - ---EXPECT-- -string(4) "Body" -array(2) { - [0]=> - string(15) "HTTP/1.0 200 Ok" - [1]=> - string(0) "" -} From 0548c4c1756724a89ef8310709419b08aadb2b3b Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 19 Jan 2025 17:49:53 +0100 Subject: [PATCH 060/503] Fix GHSA-pcmh-g36c-qc44: http headers without colon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The header line must contain colon otherwise it is invalid and it needs to fail. Reviewed-by: Tim Düsterhus --- ext/standard/http_fopen_wrapper.c | 51 ++++++++++++++----- ext/standard/tests/http/bug47021.phpt | 22 ++++---- ext/standard/tests/http/bug75535.phpt | 4 +- .../tests/http/ghsa-pcmh-g36c-qc44-001.phpt | 51 +++++++++++++++++++ .../tests/http/ghsa-pcmh-g36c-qc44-002.phpt | 51 +++++++++++++++++++ 5 files changed, 154 insertions(+), 25 deletions(-) create mode 100644 ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt create mode 100644 ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 66f356222b4e0..66daa9134afbc 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -118,6 +118,7 @@ static bool check_has_header(const char *headers, const char *header) { typedef struct _php_stream_http_response_header_info { php_stream_filter *transfer_encoding; size_t file_size; + bool error; bool follow_location; char location[HTTP_HEADER_BLOCK_SIZE]; } php_stream_http_response_header_info; @@ -127,6 +128,7 @@ static void php_stream_http_response_header_info_init( { header_info->transfer_encoding = NULL; header_info->file_size = 0; + header_info->error = false; header_info->follow_location = 1; header_info->location[0] = '\0'; } @@ -164,10 +166,11 @@ static bool php_stream_http_response_header_trim(char *http_header_line, /* Process folding headers of the current line and if there are none, parse last full response * header line. It returns NULL if the last header is finished, otherwise it returns updated * last header line. */ -static zend_string *php_stream_http_response_headers_parse(php_stream *stream, - php_stream_context *context, int options, zend_string *last_header_line_str, - char *header_line, size_t *header_line_length, int response_code, - zval *response_header, php_stream_http_response_header_info *header_info) +static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *wrapper, + php_stream *stream, php_stream_context *context, int options, + zend_string *last_header_line_str, char *header_line, size_t *header_line_length, + int response_code, zval *response_header, + php_stream_http_response_header_info *header_info) { char *last_header_line = ZSTR_VAL(last_header_line_str); size_t last_header_line_length = ZSTR_LEN(last_header_line_str); @@ -209,6 +212,19 @@ static zend_string *php_stream_http_response_headers_parse(php_stream *stream, /* Find header separator position. */ char *last_header_value = memchr(last_header_line, ':', last_header_line_length); if (last_header_value) { + /* Verify there is no space in header name */ + char *last_header_name = last_header_line + 1; + while (last_header_name < last_header_value) { + if (*last_header_name == ' ' || *last_header_name == '\t') { + header_info->error = true; + php_stream_wrapper_log_error(wrapper, options, + "HTTP invalid response format (space in header name)!"); + zend_string_efree(last_header_line_str); + return NULL; + } + ++last_header_name; + } + last_header_value++; /* Skip ':'. */ /* Strip leading whitespace. */ @@ -217,9 +233,12 @@ static zend_string *php_stream_http_response_headers_parse(php_stream *stream, last_header_value++; } } else { - /* There is no colon. Set the value to the end of the header line, which is effectively - * an empty string. */ - last_header_value = last_header_line_end; + /* There is no colon which means invalid response so error. */ + header_info->error = true; + php_stream_wrapper_log_error(wrapper, options, + "HTTP invalid response format (no colon in header line)!"); + zend_string_efree(last_header_line_str); + return NULL; } bool store_header = true; @@ -926,10 +945,16 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (last_header_line_str != NULL) { /* Parse last header line. */ - last_header_line_str = php_stream_http_response_headers_parse(stream, context, - options, last_header_line_str, http_header_line, &http_header_line_length, - response_code, response_header, &header_info); - if (last_header_line_str != NULL) { + last_header_line_str = php_stream_http_response_headers_parse(wrapper, stream, + context, options, last_header_line_str, http_header_line, + &http_header_line_length, response_code, response_header, &header_info); + if (EXPECTED(last_header_line_str == NULL)) { + if (UNEXPECTED(header_info.error)) { + php_stream_close(stream); + stream = NULL; + goto out; + } + } else { /* Folding header present so continue. */ continue; } @@ -959,8 +984,8 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* If the stream was closed early, we still want to process the last line to keep BC. */ if (last_header_line_str != NULL) { - php_stream_http_response_headers_parse(stream, context, options, last_header_line_str, - NULL, NULL, response_code, response_header, &header_info); + php_stream_http_response_headers_parse(wrapper, stream, context, options, + last_header_line_str, NULL, NULL, response_code, response_header, &header_info); } if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) { diff --git a/ext/standard/tests/http/bug47021.phpt b/ext/standard/tests/http/bug47021.phpt index 326eceb687a52..168721f4ec1b6 100644 --- a/ext/standard/tests/http/bug47021.phpt +++ b/ext/standard/tests/http/bug47021.phpt @@ -70,23 +70,27 @@ do_test(1, true); echo "\n"; ?> ---EXPECT-- +--EXPECTF-- + Type='text/plain' Hello -Size=5 -World + +Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s + Type='text/plain' Hello -Size=5 -World + +Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s + Type='text/plain' Hello -Size=5 -World + +Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s + Type='text/plain' Hello -Size=5 -World + +Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s diff --git a/ext/standard/tests/http/bug75535.phpt b/ext/standard/tests/http/bug75535.phpt index 7b015890d2f51..94348d1a027aa 100644 --- a/ext/standard/tests/http/bug75535.phpt +++ b/ext/standard/tests/http/bug75535.phpt @@ -21,9 +21,7 @@ http_server_kill($pid); --EXPECT-- string(0) "" -array(2) { +array(1) { [0]=> string(15) "HTTP/1.0 200 Ok" - [1]=> - string(14) "Content-Length" } diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt new file mode 100644 index 0000000000000..bb7945ce62d0e --- /dev/null +++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt @@ -0,0 +1,51 @@ +--TEST-- +GHSA-pcmh-g36c-qc44: Header parser of http stream wrapper does not verify header name and colon (colon) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html\r\nWrong-Header\r\nGood-Header: test\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s +bool(false) +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(23) "Content-Type: text/html" +} diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt new file mode 100644 index 0000000000000..1d0e4fa70a2c9 --- /dev/null +++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt @@ -0,0 +1,51 @@ +--TEST-- +GHSA-pcmh-g36c-qc44: Header parser of http stream wrapper does not verify header name and colon (name) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html\r\nWrong-Header : test\r\nGood-Header: test\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (space in header name)! in %s +bool(false) +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(23) "Content-Type: text/html" +} From ac1a054bb3eb5994a199e8b18cca28cbabf5943e Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 4 Mar 2025 09:01:34 +0100 Subject: [PATCH 061/503] Fix GHSA-52jp-hrpf-2jff: http redirect location truncation It converts the allocation of location to be on heap instead of stack and errors if the location length is greater than 8086 bytes. --- ext/standard/http_fopen_wrapper.c | 87 ++++++++++++------- .../tests/http/ghsa-52jp-hrpf-2jff-001.phpt | 58 +++++++++++++ .../tests/http/ghsa-52jp-hrpf-2jff-002.phpt | 55 ++++++++++++ 3 files changed, 168 insertions(+), 32 deletions(-) create mode 100644 ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt create mode 100644 ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 66daa9134afbc..dbed175d06421 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -67,15 +67,16 @@ #include "php_fopen_wrappers.h" -#define HTTP_HEADER_BLOCK_SIZE 1024 -#define PHP_URL_REDIRECT_MAX 20 -#define HTTP_HEADER_USER_AGENT 1 -#define HTTP_HEADER_HOST 2 -#define HTTP_HEADER_AUTH 4 -#define HTTP_HEADER_FROM 8 -#define HTTP_HEADER_CONTENT_LENGTH 16 -#define HTTP_HEADER_TYPE 32 -#define HTTP_HEADER_CONNECTION 64 +#define HTTP_HEADER_BLOCK_SIZE 1024 +#define HTTP_HEADER_MAX_LOCATION_SIZE 8182 /* 8192 - 10 (size of "Location: ") */ +#define PHP_URL_REDIRECT_MAX 20 +#define HTTP_HEADER_USER_AGENT 1 +#define HTTP_HEADER_HOST 2 +#define HTTP_HEADER_AUTH 4 +#define HTTP_HEADER_FROM 8 +#define HTTP_HEADER_CONTENT_LENGTH 16 +#define HTTP_HEADER_TYPE 32 +#define HTTP_HEADER_CONNECTION 64 #define HTTP_WRAPPER_HEADER_INIT 1 #define HTTP_WRAPPER_REDIRECTED 2 @@ -120,17 +121,15 @@ typedef struct _php_stream_http_response_header_info { size_t file_size; bool error; bool follow_location; - char location[HTTP_HEADER_BLOCK_SIZE]; + char *location; + size_t location_len; } php_stream_http_response_header_info; static void php_stream_http_response_header_info_init( php_stream_http_response_header_info *header_info) { - header_info->transfer_encoding = NULL; - header_info->file_size = 0; - header_info->error = false; + memset(header_info, 0, sizeof(php_stream_http_response_header_info)); header_info->follow_location = 1; - header_info->location[0] = '\0'; } /* Trim white spaces from response header line and update its length */ @@ -256,7 +255,22 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w * RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */ header_info->follow_location = 0; } - strlcpy(header_info->location, last_header_value, sizeof(header_info->location)); + size_t last_header_value_len = strlen(last_header_value); + if (last_header_value_len > HTTP_HEADER_MAX_LOCATION_SIZE) { + header_info->error = true; + php_stream_wrapper_log_error(wrapper, options, + "HTTP Location header size is over the limit of %d bytes", + HTTP_HEADER_MAX_LOCATION_SIZE); + zend_string_efree(last_header_line_str); + return NULL; + } + if (header_info->location_len == 0) { + header_info->location = emalloc(last_header_value_len + 1); + } else if (header_info->location_len <= last_header_value_len) { + header_info->location = erealloc(header_info->location, last_header_value_len + 1); + } + header_info->location_len = last_header_value_len; + memcpy(header_info->location, last_header_value, last_header_value_len + 1); } else if (!strncasecmp(last_header_line, "Content-Type:", sizeof("Content-Type:")-1)) { php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, last_header_value, 0); } else if (!strncasecmp(last_header_line, "Content-Length:", sizeof("Content-Length:")-1)) { @@ -536,6 +550,8 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, } } + php_stream_http_response_header_info_init(&header_info); + if (stream == NULL) goto out; @@ -917,8 +933,6 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, } } - php_stream_http_response_header_info_init(&header_info); - /* read past HTTP headers */ while (!php_stream_eof(stream)) { size_t http_header_line_length; @@ -988,12 +1002,12 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, last_header_line_str, NULL, NULL, response_code, response_header, &header_info); } - if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) { + if (!reqok || (header_info.location != NULL && header_info.follow_location)) { if (!header_info.follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) { goto out; } - if (header_info.location[0] != '\0') + if (header_info.location != NULL) php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, header_info.location, 0); php_stream_close(stream); @@ -1004,18 +1018,17 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, header_info.transfer_encoding = NULL; } - if (header_info.location[0] != '\0') { + if (header_info.location != NULL) { - char new_path[HTTP_HEADER_BLOCK_SIZE]; - char loc_path[HTTP_HEADER_BLOCK_SIZE]; + char *new_path = NULL; - *new_path='\0'; if (strlen(header_info.location) < 8 || (strncasecmp(header_info.location, "http://", sizeof("http://")-1) && strncasecmp(header_info.location, "https://", sizeof("https://")-1) && strncasecmp(header_info.location, "ftp://", sizeof("ftp://")-1) && strncasecmp(header_info.location, "ftps://", sizeof("ftps://")-1))) { + char *loc_path = NULL; if (*header_info.location != '/') { if (*(header_info.location+1) != '\0' && resource->path) { char *s = strrchr(ZSTR_VAL(resource->path), '/'); @@ -1033,31 +1046,35 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (resource->path && ZSTR_VAL(resource->path)[0] == '/' && ZSTR_VAL(resource->path)[1] == '\0') { - snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", - ZSTR_VAL(resource->path), header_info.location); + spprintf(&loc_path, 0, "%s%s", ZSTR_VAL(resource->path), header_info.location); } else { - snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", - ZSTR_VAL(resource->path), header_info.location); + spprintf(&loc_path, 0, "%s/%s", ZSTR_VAL(resource->path), header_info.location); } } else { - snprintf(loc_path, sizeof(loc_path) - 1, "/%s", header_info.location); + spprintf(&loc_path, 0, "/%s", header_info.location); } } else { - strlcpy(loc_path, header_info.location, sizeof(loc_path)); + loc_path = header_info.location; + header_info.location = NULL; } if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) { - snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path); + spprintf(&new_path, 0, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), + ZSTR_VAL(resource->host), resource->port, loc_path); } else { - snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), loc_path); + spprintf(&new_path, 0, "%s://%s%s", ZSTR_VAL(resource->scheme), + ZSTR_VAL(resource->host), loc_path); } + efree(loc_path); } else { - strlcpy(new_path, header_info.location, sizeof(new_path)); + new_path = header_info.location; + header_info.location = NULL; } php_url_free(resource); /* check for invalid redirection URLs */ if ((resource = php_url_parse(new_path)) == NULL) { php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path); + efree(new_path); goto out; } @@ -1069,6 +1086,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, while (s < e) { \ if (iscntrl(*s)) { \ php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path); \ + efree(new_path); \ goto out; \ } \ s++; \ @@ -1091,6 +1109,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, stream = php_stream_url_wrap_http_ex( wrapper, new_path, mode, options, opened_path, context, --redirect_max, new_flags, response_header STREAMS_CC); + efree(new_path); } else { php_stream_wrapper_log_error(wrapper, options, "HTTP request failed! %s", tmp_line); } @@ -1103,6 +1122,10 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, efree(http_header_line); } + if (header_info.location != NULL) { + efree(header_info.location); + } + if (resource) { php_url_free(resource); } diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt new file mode 100644 index 0000000000000..744cff9cc72f2 --- /dev/null +++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt @@ -0,0 +1,58 @@ +--TEST-- +GHSA-52jp-hrpf-2jff: HTTP stream wrapper truncate redirect location to 1024 bytes (success) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + $loc = str_repeat("y", 8000); + fwrite($conn, "HTTP/1.0 301 Ok\r\nContent-Type: text/html;\r\nLocation: $loc\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + case STREAM_NOTIFY_REDIRECTED: + echo "Redirected: "; + var_dump($message); + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html; +Redirected: string(8000) "%s" + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: %s +string(0) "" +array(3) { + [0]=> + string(15) "HTTP/1.0 301 Ok" + [1]=> + string(24) "Content-Type: text/html;" + [2]=> + string(8010) "Location: %s" +} diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt new file mode 100644 index 0000000000000..bc71fd4e41167 --- /dev/null +++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt @@ -0,0 +1,55 @@ +--TEST-- +GHSA-52jp-hrpf-2jff: HTTP stream wrapper truncate redirect location to 1024 bytes (over limit) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + $loc = str_repeat("y", 9000); + fwrite($conn, "HTTP/1.0 301 Ok\r\nContent-Type: text/html;\r\nLocation: $loc\r\n\r\nbody\r\n"); +CODE; + +$clientCode = <<<'CODE' + function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) { + switch($notification_code) { + case STREAM_NOTIFY_MIME_TYPE_IS: + echo "Found the mime-type: ", $message, PHP_EOL; + break; + case STREAM_NOTIFY_REDIRECTED: + echo "Redirected: "; + var_dump($message); + } + } + + $ctx = stream_context_create(); + stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); + var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +Found the mime-type: text/html; + +Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP Location header size is over the limit of 8182 bytes in %s +string(0) "" +array(2) { + [0]=> + string(15) "HTTP/1.0 301 Ok" + [1]=> + string(24) "Content-Type: text/html;" +} From 41d49abbd99dab06cdae4834db664435f8177174 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 14 Feb 2025 19:17:22 +0100 Subject: [PATCH 062/503] Fix GHSA-hgf5-96fm-v528: http user header check of crlf --- ext/standard/http_fopen_wrapper.c | 2 +- .../tests/http/ghsa-hgf5-96fm-v528-001.phpt | 65 +++++++++++++++++++ .../tests/http/ghsa-hgf5-96fm-v528-002.phpt | 62 ++++++++++++++++++ .../tests/http/ghsa-hgf5-96fm-v528-003.phpt | 64 ++++++++++++++++++ 4 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index dbed175d06421..46169e9569e26 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -108,7 +108,7 @@ static inline void strip_header(char *header_bag, char *lc_header_bag, static bool check_has_header(const char *headers, const char *header) { const char *s = headers; while ((s = strstr(s, header))) { - if (s == headers || *(s-1) == '\n') { + if (s == headers || (*(s-1) == '\n' && *(s-2) == '\r')) { return 1; } s++; diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt new file mode 100644 index 0000000000000..c40123560ef1e --- /dev/null +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt @@ -0,0 +1,65 @@ +--TEST-- +GHSA-hgf5-96fm-v528: Stream HTTP wrapper header check might omit basic auth header (incorrect inside pos) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + $result = fread($conn, 1024); + $encoded_result = base64_encode($result); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n"); + +CODE; + +$clientCode = <<<'CODE' + $opts = [ + "http" => [ + "method" => "GET", + "header" => "Cookie: foo=bar\nauthorization:x\r\n" + ] + ]; + $ctx = stream_context_create($opts); + var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +array(7) { + [0]=> + string(14) "GET / HTTP/1.1" + [1]=> + string(33) "Authorization: Basic dXNlcjpwd2Q=" + [2]=> + string(21) "Host: 127.0.0.1:%d" + [3]=> + string(17) "Connection: close" + [4]=> + string(31) "Cookie: foo=bar +authorization:x" + [5]=> + string(0) "" + [6]=> + string(0) "" +} +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(38) "Content-Type: text/html; charset=utf-8" +} diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt new file mode 100644 index 0000000000000..37a47df060a1c --- /dev/null +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt @@ -0,0 +1,62 @@ +--TEST-- +GHSA-hgf5-96fm-v528: Header parser of http stream wrapper does not handle folded headers (correct start pos) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + $result = fread($conn, 1024); + $encoded_result = base64_encode($result); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n"); + +CODE; + +$clientCode = <<<'CODE' + $opts = [ + "http" => [ + "method" => "GET", + "header" => "Authorization: Bearer x\r\n" + ] + ]; + $ctx = stream_context_create($opts); + var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +array(6) { + [0]=> + string(14) "GET / HTTP/1.1" + [1]=> + string(21) "Host: 127.0.0.1:%d" + [2]=> + string(17) "Connection: close" + [3]=> + string(23) "Authorization: Bearer x" + [4]=> + string(0) "" + [5]=> + string(0) "" +} +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(38) "Content-Type: text/html; charset=utf-8" +} diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt new file mode 100644 index 0000000000000..6c84679ff63bd --- /dev/null +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt @@ -0,0 +1,64 @@ +--TEST-- +GHSA-hgf5-96fm-v528: Header parser of http stream wrapper does not handle folded headers (correct middle pos) +--FILE-- + [ + "tcp_nodelay" => true + ] + ]); + + $server = stream_socket_server( + "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server); + + phpt_notify(message:"server-accepted"); + + $result = fread($conn, 1024); + $encoded_result = base64_encode($result); + + fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n"); + +CODE; + +$clientCode = <<<'CODE' + $opts = [ + "http" => [ + "method" => "GET", + "header" => "Cookie: x=y\r\nAuthorization: Bearer x\r\n" + ] + ]; + $ctx = stream_context_create($opts); + var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); + var_dump($http_response_header); +CODE; + +include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECTF-- +array(7) { + [0]=> + string(14) "GET / HTTP/1.1" + [1]=> + string(21) "Host: 127.0.0.1:%d" + [2]=> + string(17) "Connection: close" + [3]=> + string(11) "Cookie: x=y" + [4]=> + string(23) "Authorization: Bearer x" + [5]=> + string(0) "" + [6]=> + string(0) "" +} +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(38) "Content-Type: text/html; charset=utf-8" +} From b6004a043c16b211d462218fbb3f72db68ec2b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 20 Nov 2024 10:47:27 +0100 Subject: [PATCH 063/503] Fix GHSA-p3x9-6h7p-cgfc: libxml streams wrong `content-type` on redirect libxml streams use wrong content-type header when requesting a redirected resource. --- ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt | 60 +++++++++++++++++ ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt | 60 +++++++++++++++++ ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt | 60 +++++++++++++++++ ext/libxml/libxml.c | 77 ++++++++++++---------- 4 files changed, 224 insertions(+), 33 deletions(-) create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt new file mode 100644 index 0000000000000..47212cb34100a --- /dev/null +++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt @@ -0,0 +1,60 @@ +--TEST-- +GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Basic) +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- + + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + + EOT; + // Intentionally using non-standard casing for content-type to verify it is matched not case sensitively. + yield "data://text/plain,HTTP/1.1 200 OK\r\nconteNt-tyPe: text/html; charset=utf-8\r\n\r\n{$xml}"; +} + +['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output); +$document = new \DOMDocument(); +$document->loadHTMLFile($uri); + +$h1 = $document->getElementsByTagName('h1'); +var_dump($h1->length); +var_dump($document->saveHTML()); +http_server_kill($pid); +?> +--EXPECT-- +int(1) +string(266) " + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + +" diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt new file mode 100644 index 0000000000000..a7eff3b9a8b76 --- /dev/null +++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt @@ -0,0 +1,60 @@ +--TEST-- +GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Missing content-type) +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- + + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + + EOT; + // Missing content-type in actual response. + yield "data://text/plain,HTTP/1.1 200 OK\r\n\r\n{$xml}"; +} + +['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output); +$document = new \DOMDocument(); +$document->loadHTMLFile($uri); + +$h1 = $document->getElementsByTagName('h1'); +var_dump($h1->length); +var_dump($document->saveHTML()); +http_server_kill($pid); +?> +--EXPECT-- +int(1) +string(266) " + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + +" diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt new file mode 100644 index 0000000000000..178b35f3525a5 --- /dev/null +++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt @@ -0,0 +1,60 @@ +--TEST-- +GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Reason with colon) +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- + + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + + EOT; + // Missing content-type in actual response. + yield "data://text/plain,HTTP/1.1 200 OK: This is fine\r\n\r\n{$xml}"; +} + +['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output); +$document = new \DOMDocument(); +$document->loadHTMLFile($uri); + +$h1 = $document->getElementsByTagName('h1'); +var_dump($h1->length); +var_dump($document->saveHTML()); +http_server_kill($pid); +?> +--EXPECT-- +int(1) +string(266) " + + + GHSA-p3x9-6h7p-cgfc + + + + + + +

GHSA-p3x9-6h7p-cgfc

+ + +" diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index dc5e77909523d..3311346d4bcfb 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -374,42 +374,53 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) if (Z_TYPE(s->wrapperdata) == IS_ARRAY) { zval *header; - ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) { + /* Scan backwards: The header array might contain the headers for multiple responses, if + * a redirect was followed. + */ + ZEND_HASH_REVERSE_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) { const char buf[] = "Content-Type:"; - if (Z_TYPE_P(header) == IS_STRING && - !zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) { - char *needle = estrdup("charset="); - char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header)); - char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1); - - if (encoding) { - char *end; - - encoding += sizeof("charset=")-1; - if (*encoding == '"') { - encoding++; - } - end = strchr(encoding, ';'); - if (end == NULL) { - end = encoding + strlen(encoding); - } - end--; /* end == encoding-1 isn't a buffer underrun */ - while (*end == ' ' || *end == '\t') { - end--; - } - if (*end == '"') { - end--; - } - if (encoding >= end) continue; - *(end+1) = '\0'; - enc = xmlParseCharEncoding(encoding); - if (enc <= XML_CHAR_ENCODING_NONE) { - enc = XML_CHAR_ENCODING_NONE; + if (Z_TYPE_P(header) == IS_STRING) { + /* If no colon is found in the header, we assume it's the HTTP status line and bail out. */ + char *colon = memchr(Z_STRVAL_P(header), ':', Z_STRLEN_P(header)); + char *space = memchr(Z_STRVAL_P(header), ' ', Z_STRLEN_P(header)); + if (colon == NULL || space < colon) { + break; + } + + if (!zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) { + char *needle = estrdup("charset="); + char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header)); + char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1); + + if (encoding) { + char *end; + + encoding += sizeof("charset=")-1; + if (*encoding == '"') { + encoding++; + } + end = strchr(encoding, ';'); + if (end == NULL) { + end = encoding + strlen(encoding); + } + end--; /* end == encoding-1 isn't a buffer underrun */ + while (*end == ' ' || *end == '\t') { + end--; + } + if (*end == '"') { + end--; + } + if (encoding >= end) continue; + *(end+1) = '\0'; + enc = xmlParseCharEncoding(encoding); + if (enc <= XML_CHAR_ENCODING_NONE) { + enc = XML_CHAR_ENCODING_NONE; + } } + efree(haystack); + efree(needle); + break; /* found content-type */ } - efree(haystack); - efree(needle); - break; /* found content-type */ } } ZEND_HASH_FOREACH_END(); } From 0e715e71d945b68f8ccedd62c5960df747af6625 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 18 Dec 2024 18:44:05 +0100 Subject: [PATCH 064/503] Fix GHSA-wg4p-4hqh-c3g9 --- ext/xml/tests/toffset_bounds.phpt | 42 +++++++++++++++++++++++++++++++ ext/xml/xml.c | 12 ++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 ext/xml/tests/toffset_bounds.phpt diff --git a/ext/xml/tests/toffset_bounds.phpt b/ext/xml/tests/toffset_bounds.phpt new file mode 100644 index 0000000000000..5a3fd22f86cd7 --- /dev/null +++ b/ext/xml/tests/toffset_bounds.phpt @@ -0,0 +1,42 @@ +--TEST-- +XML_OPTION_SKIP_TAGSTART bounds +--EXTENSIONS-- +xml +--FILE-- +"; +$parser = xml_parser_create(); +xml_parser_set_option($parser, XML_OPTION_SKIP_TAGSTART, 100); +$res = xml_parse_into_struct($parser,$sample,$vals,$index); +var_dump($vals); +?> +--EXPECT-- +array(3) { + [0]=> + array(3) { + ["tag"]=> + string(0) "" + ["type"]=> + string(4) "open" + ["level"]=> + int(1) + } + [1]=> + array(3) { + ["tag"]=> + string(0) "" + ["type"]=> + string(8) "complete" + ["level"]=> + int(2) + } + [2]=> + array(3) { + ["tag"]=> + string(0) "" + ["type"]=> + string(5) "close" + ["level"]=> + int(1) + } +} diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 56f81c4305b4f..1638f36e8ebc5 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -667,9 +667,11 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch array_init(&tag); array_init(&atr); - _xml_add_to_info(parser, ZSTR_VAL(tag_name) + parser->toffset); + char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name)); - add_assoc_string(&tag, "tag", SKIP_TAGSTART(ZSTR_VAL(tag_name))); /* cast to avoid gcc-warning */ + _xml_add_to_info(parser, skipped_tag_name); + + add_assoc_string(&tag, "tag", skipped_tag_name); add_assoc_string(&tag, "type", "open"); add_assoc_long(&tag, "level", parser->level); @@ -736,9 +738,11 @@ void _xml_endElementHandler(void *userData, const XML_Char *name) } else { array_init(&tag); - _xml_add_to_info(parser, ZSTR_VAL(tag_name) + parser->toffset); + char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name)); + + _xml_add_to_info(parser, skipped_tag_name); - add_assoc_string(&tag, "tag", SKIP_TAGSTART(ZSTR_VAL(tag_name))); /* cast to avoid gcc-warning */ + add_assoc_string(&tag, "tag", skipped_tag_name); add_assoc_string(&tag, "type", "close"); add_assoc_long(&tag, "level", parser->level); From 74d548bf58d878c99f83671986728b65cb5b07fc Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 7 Mar 2025 13:40:40 +0100 Subject: [PATCH 065/503] Update NEWS with entries for security fixes --- NEWS | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7324aaf5bef54..87a7e7d080c44 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,21 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.32 +13 Mar 2025, PHP 8.1.32 + +- LibXML: + . Fixed GHSA-wg4p-4hqh-c3g9 (Reocurrence of #72714). (nielsdos) + . Fixed GHSA-p3x9-6h7p-cgfc (libxml streams use wrong `content-type` header + when requesting a redirected resource). (CVE-2025-1219) (timwolla) + +- Streams: + . Fixed GHSA-hgf54-96fm-v528 (Stream HTTP wrapper header check might omit + basic auth header). (CVE-2025-1736) (Jakub Zelenka) + . Fixed GHSA-52jp-hrpf-2jff (Stream HTTP wrapper truncate redirect location + to 1024 bytes). (CVE-2025-1861) (Jakub Zelenka) + . Fixed GHSA-pcmh-g36c-qc44 (Streams HTTP wrapper does not fail for headers + without colon). (CVE-2025-1734) (Jakub Zelenka) + . Fixed GHSA-v8xr-gpvj-cx9g (Header parser of `http` stream wrapper does not + handle folded headers). (CVE-2025-1217) (Jakub Zelenka) - Windows: . Fixed phpize for Windows 11 (24H2). (bwoebi) From ef2c459941b5ffae501e5311f5ac2041aadbe461 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 13 Nov 2024 01:41:40 +0100 Subject: [PATCH 066/503] Use-after-free for ??= due to incorrect live-range calculation Fixes GHSA-rwp7-7vc6-8477 --- NEWS | 2 ++ Zend/tests/ghsa-rwp7-7vc6-8477_001.phpt | 26 +++++++++++++++++++++++++ Zend/tests/ghsa-rwp7-7vc6-8477_002.phpt | 24 +++++++++++++++++++++++ Zend/tests/ghsa-rwp7-7vc6-8477_003.phpt | 22 +++++++++++++++++++++ Zend/zend_opcode.c | 8 ++++++++ 5 files changed, 82 insertions(+) create mode 100644 Zend/tests/ghsa-rwp7-7vc6-8477_001.phpt create mode 100644 Zend/tests/ghsa-rwp7-7vc6-8477_002.phpt create mode 100644 Zend/tests/ghsa-rwp7-7vc6-8477_003.phpt diff --git a/NEWS b/NEWS index 07effa01580c8..aeffd4ece47dc 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,8 @@ PHP NEWS `__callStatic` is allowed). (timwolla) . Fixed bug GH-17797 (zend_test_compile_string crash on invalid script path). (David Carlier) + . Fixed GHSA-rwp7-7vc6-8477 (Reference counting in php_request_shutdown + causes Use-After-Free). (CVE-2024-11235) (ilutov) - DOM: . Fixed bug GH-17847 (xinclude destroys live node). (nielsdos) diff --git a/Zend/tests/ghsa-rwp7-7vc6-8477_001.phpt b/Zend/tests/ghsa-rwp7-7vc6-8477_001.phpt new file mode 100644 index 0000000000000..d0e9ddcba410b --- /dev/null +++ b/Zend/tests/ghsa-rwp7-7vc6-8477_001.phpt @@ -0,0 +1,26 @@ +--TEST-- +GHSA-rwp7-7vc6-8477: Use-after-free for ??= due to incorrect live-range calculation +--FILE-- +foo()->baz ??= 1; +} catch (Exception $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +Hello diff --git a/Zend/tests/ghsa-rwp7-7vc6-8477_002.phpt b/Zend/tests/ghsa-rwp7-7vc6-8477_002.phpt new file mode 100644 index 0000000000000..4115d9eae26fd --- /dev/null +++ b/Zend/tests/ghsa-rwp7-7vc6-8477_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +GHSA-rwp7-7vc6-8477: Use-after-free for ??= due to incorrect live-range calculation +--FILE-- +foo()->prop ??= 'foo'; +} catch (Error $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +Cannot assign string to property Foo::$prop of type int diff --git a/Zend/tests/ghsa-rwp7-7vc6-8477_003.phpt b/Zend/tests/ghsa-rwp7-7vc6-8477_003.phpt new file mode 100644 index 0000000000000..f2808afbf84de --- /dev/null +++ b/Zend/tests/ghsa-rwp7-7vc6-8477_003.phpt @@ -0,0 +1,22 @@ +--TEST-- +GHSA-rwp7-7vc6-8477: Use-after-free for ??= due to incorrect live-range calculation +--FILE-- +prop ??= 'foo'; +} catch (Error $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +Cannot assign string to property Foo::$prop of type int diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 55bf81376d99d..06f411a1d3663 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -922,6 +922,14 @@ static void zend_calc_live_ranges( opnum--; opline--; + /* SEPARATE always redeclares its op1. For the purposes of live-ranges, + * its declaration is irrelevant. Don't terminate the current live-range + * to avoid breaking special handling of COPY_TMP. */ + if (opline->opcode == ZEND_SEPARATE) { + ZEND_ASSERT(opline->op1.var == opline->result.var); + continue; + } + if ((opline->result_type & (IS_TMP_VAR|IS_VAR)) && !is_fake_def(opline)) { uint32_t var_num = EX_VAR_TO_NUM(opline->result.var) - var_offset; /* Defs without uses can occur for two reasons: Either because the result is From 858c378930eb4172b94528e80c95058207469a04 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 11 Mar 2025 16:34:23 -0500 Subject: [PATCH 067/503] PHP-8.1 is now for PHP 8.1.33-dev --- NEWS | 4 ++++ Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 87a7e7d080c44..67f6b8f728be7 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +?? ??? ????, PHP 8.1.33 + + + 13 Mar 2025, PHP 8.1.32 - LibXML: diff --git a/Zend/zend.h b/Zend/zend.h index dcf69979f952c..6562119e8363c 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.31-dev" +#define ZEND_VERSION "4.1.33-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index f6902707abb15..0f45db92ba7de 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.31-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.33-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index bff6722583474..2aee6f19d16a4 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 31 +#define PHP_RELEASE_VERSION 33 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.31-dev" -#define PHP_VERSION_ID 80131 +#define PHP_VERSION "8.1.33-dev" +#define PHP_VERSION_ID 80133 From a8d3a8006739b8aad2a190be90a0491739be6c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 19 Nov 2024 10:29:50 +0100 Subject: [PATCH 068/503] Fix GHSA-p3x9-6h7p-cgfc: libxml streams wrong `content-type` on redirect libxml streams use wrong content-type header when requesting a redirected resource. --- ext/libxml/mime_sniff.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ext/libxml/mime_sniff.c b/ext/libxml/mime_sniff.c index 79ce1dc46b5e0..0ca032f9b795e 100644 --- a/ext/libxml/mime_sniff.c +++ b/ext/libxml/mime_sniff.c @@ -308,11 +308,21 @@ PHP_LIBXML_API zend_string *php_libxml_sniff_charset_from_stream(const php_strea if (Z_TYPE(s->wrapperdata) == IS_ARRAY) { zval *header; - ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) { - const char buf[] = "Content-Type:"; - if (Z_TYPE_P(header) == IS_STRING && - !zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) { - return php_libxml_sniff_charset_from_string(Z_STRVAL_P(header) + sizeof(buf) - 1, Z_STRVAL_P(header) + Z_STRLEN_P(header)); + /* Scan backwards: The header array might contain the headers for multiple responses, if + * a redirect was followed. + */ + ZEND_HASH_REVERSE_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) { + if (Z_TYPE_P(header) == IS_STRING) { + /* If no colon is found in the header, we assume it's the HTTP status line and bail out. */ + char *colon = memchr(Z_STRVAL_P(header), ':', Z_STRLEN_P(header)); + char *space = memchr(Z_STRVAL_P(header), ' ', Z_STRLEN_P(header)); + if (colon == NULL || space < colon) { + return NULL; + } + + if (zend_string_starts_with_literal_ci(Z_STR_P(header), "content-type:")) { + return php_libxml_sniff_charset_from_string(Z_STRVAL_P(header) + strlen("content-type:"), Z_STRVAL_P(header) + Z_STRLEN_P(header)); + } } } ZEND_HASH_FOREACH_END(); } From 8156a89eff41e4602d676bbe17f08c7b0f960bb4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 11 Mar 2025 23:06:26 +0100 Subject: [PATCH 069/503] Fix incorrectly merged bug75535.phpt Co-authored-by: Jakub Zelenka --- ext/standard/tests/http/bug75535.phpt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ext/standard/tests/http/bug75535.phpt b/ext/standard/tests/http/bug75535.phpt index 7dbea6373304b..94348d1a027aa 100644 --- a/ext/standard/tests/http/bug75535.phpt +++ b/ext/standard/tests/http/bug75535.phpt @@ -14,25 +14,14 @@ $responses = array( ['pid' => $pid, 'uri' => $uri] = http_server($responses, $output); -var_dump(http_get_last_response_headers()); - var_dump(file_get_contents($uri)); var_dump($http_response_header); -var_dump(http_get_last_response_headers()); http_server_kill($pid); -?> --EXPECT-- -NULL string(0) "" array(1) { [0]=> string(15) "HTTP/1.0 200 Ok" } -array(2) { - [0]=> - string(15) "HTTP/1.0 200 Ok" - [1]=> - string(14) "Content-Length" -} From b617b0832ccdb25fad861091564fee077f5983fb Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 11 Mar 2025 18:31:23 -0400 Subject: [PATCH 070/503] PHP-8.2 is now for PHP 8.2.29-dev --- NEWS | 4 +++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index f2f685e6f6cfc..a6429585cf2fb 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.28 +?? ??? ????, PHP 8.2.29 + +13 Mar 2025, PHP 8.2.28 - Core: . Fixed bug GH-17211 (observer segfault on function loaded with dl()). diff --git a/Zend/zend.h b/Zend/zend.h index 7deb59f432199..71e5908f334f0 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.28-dev" +#define ZEND_VERSION "4.2.29-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 4d63418347ef3..c70ce436721a8 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.28-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.29-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index d035df8c52919..cd9671425f86f 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 -#define PHP_RELEASE_VERSION 28 +#define PHP_RELEASE_VERSION 29 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.28-dev" -#define PHP_VERSION_ID 80228 +#define PHP_VERSION "8.2.29-dev" +#define PHP_VERSION_ID 80229 From 009b5e2bfd497c3abdd645ec60bbdb90787de6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 16 Dec 2024 22:16:18 +0100 Subject: [PATCH 071/503] fix GH-8533: dynamic libphp linking on Mac Pass the -dynamiclib flag to libtool to build a valid Mac dylib. Closes GH-8533. --- .gitignore | 3 +++ NEWS | 3 +++ build/Makefile.global | 4 ++++ build/php.m4 | 9 +++++++++ sapi/embed/config.m4 | 5 ++++- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b9e60cc6b5bde..4e95d9a9da33d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ # Libtool library files generated during build process *.la +# Mac shared library files generated during build process +*.dylib + # Directories created by Libtool for storing generated library files .libs/ diff --git a/NEWS b/NEWS index aeffd4ece47dc..c54938982f5fa 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ PHP NEWS . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) +- Embed: + . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) + - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) diff --git a/build/Makefile.global b/build/Makefile.global index b11ce20aae87a..ec19efcbc5894 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -19,6 +19,10 @@ libphp.la: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(LIBTOOL) --tag=CC --mode=link $(CC) $(LIBPHP_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ -@$(LIBTOOL) --silent --tag=CC --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 +libphp.dylib: libphp.la + $(LIBTOOL) --tag=CC --mode=link $(CC) -dynamiclib $(LIBPHP_CFLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -rpath $(phptempdir) -install_name @rpath/$@ $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ + -@$(LIBTOOL) --silent --tag=CC --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 + libs/libphp.bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ && cp $@ libs/libphp.so diff --git a/build/php.m4 b/build/php.m4 index 61ee5c167536b..142ddf08fd98b 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -764,6 +764,14 @@ AC_DEFUN([PHP_BUILD_SHARED],[ php_lo=$shared_lo ]) +dnl +dnl PHP_BUILD_SHARED_DYLIB +dnl +AC_DEFUN([PHP_BUILD_SHARED_DYLIB],[ + PHP_BUILD_SHARED + OVERALL_TARGET=libphp.dylib +]) + dnl dnl PHP_BUILD_STATIC dnl @@ -876,6 +884,7 @@ AC_DEFUN([PHP_SELECT_SAPI],[ case "$2" in static[)] PHP_BUILD_STATIC;; shared[)] PHP_BUILD_SHARED;; + shared-dylib[)] PHP_BUILD_SHARED_DYLIB;; bundle[)] PHP_BUILD_BUNDLE;; esac install_sapi="install-sapi" diff --git a/sapi/embed/config.m4 b/sapi/embed/config.m4 index 39d7dcf0a3ff2..71aab64e6fa52 100644 --- a/sapi/embed/config.m4 +++ b/sapi/embed/config.m4 @@ -11,7 +11,10 @@ if test "$PHP_EMBED" != "no"; then case "$PHP_EMBED" in yes|shared) LIBPHP_CFLAGS="-shared" - PHP_EMBED_TYPE=shared + AS_CASE(["$host_alias"], [*darwin*], [ + SAPI_SHARED="libs/libphp.dylib" + PHP_EMBED_TYPE=shared-dylib + ], [PHP_EMBED_TYPE=shared]) INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(prefix)/lib; \$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)\$(prefix)/lib" ;; static) From 7f0d4e36de3be89c7133ad09d903e51942f74dd5 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Wed, 12 Mar 2025 03:54:11 -0700 Subject: [PATCH 072/503] access_modifiers_002.phpt: fix test name [skip ci] (GH-18027) "Attributes" has taken on another meaning since this test was created in 2007 --- Zend/tests/access_modifiers/access_modifiers_002.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/tests/access_modifiers/access_modifiers_002.phpt b/Zend/tests/access_modifiers/access_modifiers_002.phpt index 9830258c619b4..835d7445aac08 100644 --- a/Zend/tests/access_modifiers/access_modifiers_002.phpt +++ b/Zend/tests/access_modifiers/access_modifiers_002.phpt @@ -1,5 +1,5 @@ --TEST-- -using multiple access modifiers (attributes) +using multiple access modifiers (properties) --FILE-- Date: Wed, 12 Mar 2025 06:34:55 -0700 Subject: [PATCH 073/503] PHP-8.3 is now for PHP-8.3.20-dev --- NEWS | 4 ++-- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index c54938982f5fa..e899b8ac86ce8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.19 +?? ??? ????, PHP 8.3.20 - DOM: . Fix weird unpack behaviour in DOM. (nielsdos) @@ -19,7 +19,7 @@ PHP NEWS - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) -27 Feb 2025, PHP 8.3.18 +13 Feb 2025, PHP 8.3.19 - BCMath: . Fixed bug GH-17398 (bcmul memory leak). (SakiTakamachi) diff --git a/Zend/zend.h b/Zend/zend.h index e795ac967a23d..927088ea18706 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.19-dev" +#define ZEND_VERSION "4.3.20-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 0e98613854281..a94d4958492fd 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.19-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.20-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 8b508aaa33585..3dee6de933251 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 -#define PHP_RELEASE_VERSION 19 +#define PHP_RELEASE_VERSION 20 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.19-dev" -#define PHP_VERSION_ID 80319 +#define PHP_VERSION "8.3.20-dev" +#define PHP_VERSION_ID 80320 From 8731c95b35f6838bacd12a07c50886e020aad5a6 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 3 Mar 2025 12:26:06 +0100 Subject: [PATCH 074/503] Make missing trait error recoverable We were already handling NULL as a case, but seem to have forgotten to pass the ZEND_FETCH_CLASS_EXCEPTION flag. Also make "is not a trait" error recoverable, there's no reason why it can't be. Fixes GH-17959 Closes GH-17960 --- NEWS | 2 ++ Zend/tests/traits/bugs/missing-trait.phpt | 5 ++++- Zend/tests/traits/error_002.phpt | 5 ++++- Zend/tests/traits/error_003.phpt | 5 ++++- Zend/tests/traits/error_004.phpt | 5 ++++- Zend/tests/traits/error_005.phpt | 5 ++++- Zend/tests/traits/error_006.phpt | 5 ++++- Zend/tests/traits/gh17959.phpt | 18 ++++++++++++++++++ Zend/zend_inheritance.c | 4 ++-- 9 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 Zend/tests/traits/gh17959.phpt diff --git a/NEWS b/NEWS index 18e1f76dabe2c..2268ebedc7b45 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ PHP NEWS . Fixed bug GH-17442 (Engine UAF with reference assign and dtor). (nielsdos) . Improved error message of UnhandledMatchError for zend.exception_string_param_max_len=0. (timwolla) + . Fixed bug GH-17959 (Relax missing trait fatal error to error exception). + (ilutov) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/Zend/tests/traits/bugs/missing-trait.phpt b/Zend/tests/traits/bugs/missing-trait.phpt index 4bf054e889002..0b36c47e771d7 100644 --- a/Zend/tests/traits/bugs/missing-trait.phpt +++ b/Zend/tests/traits/bugs/missing-trait.phpt @@ -12,4 +12,7 @@ $test = new TraitsTest(); ?> --EXPECTF-- -Fatal error: Trait "THello" not found in %s on line %d +Fatal error: Uncaught Error: Trait "THello" not found in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/error_002.phpt b/Zend/tests/traits/error_002.phpt index 53ad403a43373..fc9cfc5884c4c 100644 --- a/Zend/tests/traits/error_002.phpt +++ b/Zend/tests/traits/error_002.phpt @@ -9,4 +9,7 @@ class A { ?> --EXPECTF-- -Fatal error: Trait "abc" not found in %s on line %d +Fatal error: Uncaught Error: Trait "abc" not found in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/error_003.phpt b/Zend/tests/traits/error_003.phpt index fdfa0ac1fe22b..6a6d2d56d6c41 100644 --- a/Zend/tests/traits/error_003.phpt +++ b/Zend/tests/traits/error_003.phpt @@ -12,4 +12,7 @@ class A { ?> --EXPECTF-- -Fatal error: A cannot use abc - it is not a trait in %s on line %d +Fatal error: Uncaught Error: A cannot use abc - it is not a trait in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/error_004.phpt b/Zend/tests/traits/error_004.phpt index d7ff695e047b3..1e339f3d6314d 100644 --- a/Zend/tests/traits/error_004.phpt +++ b/Zend/tests/traits/error_004.phpt @@ -12,4 +12,7 @@ class A { ?> --EXPECTF-- -Fatal error: A cannot use abc - it is not a trait in %s on line %d +Fatal error: Uncaught Error: A cannot use abc - it is not a trait in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/error_005.phpt b/Zend/tests/traits/error_005.phpt index 3b8cc32f97584..dae8e1893a68c 100644 --- a/Zend/tests/traits/error_005.phpt +++ b/Zend/tests/traits/error_005.phpt @@ -12,4 +12,7 @@ class A { ?> --EXPECTF-- -Fatal error: A cannot use abc - it is not a trait in %s on line %d +Fatal error: Uncaught Error: A cannot use abc - it is not a trait in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/error_006.phpt b/Zend/tests/traits/error_006.phpt index f3ed87123cf29..5d831a9da7f12 100644 --- a/Zend/tests/traits/error_006.phpt +++ b/Zend/tests/traits/error_006.phpt @@ -12,4 +12,7 @@ class A { ?> --EXPECTF-- -Fatal error: A cannot use abc - it is not a trait in %s on line %d +Fatal error: Uncaught Error: A cannot use abc - it is not a trait in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/traits/gh17959.phpt b/Zend/tests/traits/gh17959.phpt new file mode 100644 index 0000000000000..016dd7a4a4f7c --- /dev/null +++ b/Zend/tests/traits/gh17959.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-17959: Missing trait error is recoverable +--FILE-- +getMessage(), "\n"; +} + +?> +===DONE=== +--EXPECT-- +Error: Trait "MissingTrait" not found +===DONE=== diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 807c902276a24..bcccf978e2a01 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3546,13 +3546,13 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string for (i = 0; i < ce->num_traits; i++) { zend_class_entry *trait = zend_fetch_class_by_name(ce->trait_names[i].name, - ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT); + ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(trait == NULL)) { free_alloca(traits_and_interfaces, use_heap); return NULL; } if (UNEXPECTED(!(trait->ce_flags & ZEND_ACC_TRAIT))) { - zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); + zend_throw_error(NULL, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); free_alloca(traits_and_interfaces, use_heap); return NULL; } From c3fc94c4b8570509065c49df67436597afd94bc5 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 12 Mar 2025 20:07:34 +0000 Subject: [PATCH 075/503] ext/intl: fix locale_compose/locale_lookup to be able to deal with references. close GH-18035 --- NEWS | 4 +++ ext/intl/locale/locale_methods.c | 8 +++-- .../locale_compose_lookup_references.phpt | 29 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 ext/intl/tests/locale_compose_lookup_references.phpt diff --git a/NEWS b/NEWS index e899b8ac86ce8..39ee4c46becda 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ PHP NEWS . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) +- Intl: + . Fix locale_compose and locale_lookup to work with their array argument + with values as references. (David Carlier) + - Embed: . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index d6053b6be56d3..f810a61b6be12 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -814,7 +814,7 @@ static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_ { zval *ele_value; - if ((ele_value = zend_hash_str_find(hash_arr , key_name, strlen(key_name))) != NULL ) { + if ((ele_value = zend_hash_str_find_deref(hash_arr , key_name, strlen(key_name))) != NULL ) { if(Z_TYPE_P(ele_value)!= IS_STRING ){ /* element value is not a string */ return FAILURE; @@ -857,7 +857,7 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, int isFirstSubtag = 0; /* Variant/ Extlang/Private etc. */ - if ((ele_value = zend_hash_str_find( hash_arr , key_name , strlen(key_name))) != NULL) { + if ((ele_value = zend_hash_str_find_deref( hash_arr , key_name , strlen(key_name))) != NULL) { if( Z_TYPE_P(ele_value) == IS_STRING ){ add_prefix( loc_name , key_name); @@ -869,6 +869,7 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, zval *data; ZEND_HASH_FOREACH_VAL(arr, data) { + ZVAL_DEREF(data); if(Z_TYPE_P(data) != IS_STRING) { return FAILURE; } @@ -900,7 +901,7 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, isFirstSubtag = 0; for( i=0 ; i< max_value; i++ ){ snprintf( cur_key_name , 30, "%s%d", key_name , i); - if ((ele_value = zend_hash_str_find( hash_arr , cur_key_name , strlen(cur_key_name))) != NULL) { + if ((ele_value = zend_hash_str_find_deref( hash_arr , cur_key_name , strlen(cur_key_name))) != NULL) { if( Z_TYPE_P(ele_value)!= IS_STRING ){ /* variant is not a string */ return FAILURE; @@ -1437,6 +1438,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, char **cur_arr = ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *)); ZEND_HASH_FOREACH_VAL(hash_arr, ele_value) { + ZVAL_DEREF(ele_value); /* convert the array to lowercase , also replace hyphens with the underscore and store it in cur_arr */ if(Z_TYPE_P(ele_value)!= IS_STRING) { /* element value is not a string */ diff --git a/ext/intl/tests/locale_compose_lookup_references.phpt b/ext/intl/tests/locale_compose_lookup_references.phpt new file mode 100644 index 0000000000000..f6a202f7512fa --- /dev/null +++ b/ext/intl/tests/locale_compose_lookup_references.phpt @@ -0,0 +1,29 @@ +--TEST-- +locale_compose()/locale_lookup() with values as references. +--EXTENSIONS-- +intl +--FILE-- + 'en', Locale::REGION_TAG => &$en]; + +var_dump(locale_compose($data)); + +$data = [ + 'language' => 'de', + 'script' => 'Hans', + 'region' => 'DE', + 'variant2' => 'fr', + 'variant1' => &$en, + 'private1' => 'private1', + 'private2' => 'private2', + ]; +var_dump(locale_compose($data)); +$data = ['de', &$en]; +var_dump(locale_lookup($data, "en", false, "en")); +?> +--EXPECT-- +string(5) "en_en" +string(36) "de_Hans_DE_en_fr_x_private1_private2" +string(2) "en" From ccb6d78bab61f06c5ab3ecdaf021aa321fb6675a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 12 Mar 2025 22:22:20 +0000 Subject: [PATCH 076/503] fix php_version --- main/php_version.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/main/php_version.h b/main/php_version.h index c12a5f83c175a..269397ba11e18 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -1,16 +1,8 @@ /* automatically generated by configure */ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 -<<<<<<< HEAD #define PHP_MINOR_VERSION 5 #define PHP_RELEASE_VERSION 0 #define PHP_EXTRA_VERSION "-dev" #define PHP_VERSION "8.5.0-dev" #define PHP_VERSION_ID 80500 -======= -#define PHP_MINOR_VERSION 4 -#define PHP_RELEASE_VERSION 6 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.4.6-dev" -#define PHP_VERSION_ID 80406 ->>>>>>> PHP-8.4 From ae67eb049035dca26740d85ab34dc873e86502d7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 13 Mar 2025 03:07:43 +0300 Subject: [PATCH 077/503] Update IR IR commit: 8bb0acca45a7b0f12691f4258e41462599efbd74 --- ext/opcache/jit/ir/ir_gcm.c | 5 +- ext/opcache/jit/ir/ir_sccp.c | 738 +++++++++++++++++++++++++---------- 2 files changed, 539 insertions(+), 204 deletions(-) diff --git a/ext/opcache/jit/ir/ir_gcm.c b/ext/opcache/jit/ir/ir_gcm.c index 396ba2d7f7c7b..8bd6be5d10aa0 100644 --- a/ext/opcache/jit/ir/ir_gcm.c +++ b/ext/opcache/jit/ir/ir_gcm.c @@ -413,10 +413,11 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b) n = ctx->use_lists[ref].refs; for (i = 0; i < clones_count; i++) { clone = clones[i].ref; - if (clones[i].use_count == 1) { + if (clones[i].use_count == 1 + && ctx->cfg_blocks[clones[i].block].loop_depth >= ctx->cfg_blocks[uses[clones[i].use].block].loop_depth) { /* TOTALLY_USEFUL block may be a head of a diamond above the real usage. * Sink it down to the real usage block. - * Clones with few uses we be sunk into the LCA block. + * Clones with few uses will be sunk into the LCA block. */ clones[i].block = uses[clones[i].use].block; } diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index b4f2257744145..42012f222f7ff 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -553,8 +553,7 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi } if (!may_benefit) { IR_MAKE_BOTTOM_EX(i); - if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC - || insn->op == IR_ZEXT || insn->op == IR_SEXT || insn->op == IR_EQ || insn->op == IR_NE) { + if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC) { ir_bitqueue_add(iter_worklist, i); } } else if (!ir_sccp_fold(ctx, _values, worklist, i, insn)) { @@ -562,8 +561,7 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi continue; } else if (_values[i].op == IR_BOTTOM) { insn = &ctx->ir_base[i]; - if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC - || insn->op == IR_ZEXT || insn->op == IR_SEXT || insn->op == IR_EQ || insn->op == IR_NE) { + if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC) { ir_bitqueue_add(iter_worklist, i); } } @@ -571,7 +569,7 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi IR_MAKE_BOTTOM_EX(i); } } else if (flags & IR_OP_FLAG_BB_START) { - if (insn->op == IR_MERGE || insn->op == IR_BEGIN) { + if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_BEGIN) { ir_bitqueue_add(iter_worklist, i); } if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) { @@ -919,163 +917,128 @@ static void ir_sccp_remove_if(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref } } -static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref unfeasible_inputs) +static bool ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqueue *worklist) { - ir_ref i, j, n, k, *p, use; - ir_insn *insn, *use_insn; + ir_ref old_merge_inputs, new_merge_inputs, i, *p; ir_use_list *use_list; ir_bitset life_inputs; + ir_bitset_base_t holder = 0; - insn = &ctx->ir_base[ref]; IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN); - n = insn->inputs_count; - if (n - unfeasible_inputs == 1) { - /* remove MERGE completely */ - for (j = 1; j <= n; j++) { - ir_ref input = ir_insn_op(insn, j); - if (input && IR_IS_REACHABLE(input)) { - ir_insn *input_insn = &ctx->ir_base[input]; - - IR_ASSERT(input_insn->op == IR_END || input_insn->op == IR_LOOP_END|| - input_insn->op == IR_IJMP || input_insn->op == IR_UNREACHABLE); - if (input_insn->op == IR_END || input_insn->op == IR_LOOP_END) { - ir_ref prev, next = IR_UNUSED; - ir_insn *next_insn = NULL; - - prev = input_insn->op1; - use_list = &ctx->use_lists[ref]; - if (use_list->count == 1) { - next = ctx->use_edges[use_list->refs]; - next_insn = &ctx->ir_base[next]; - } else { - k = 0; - p = &ctx->use_edges[use_list->refs]; - while (k < use_list->count) { - use = *p; - use_insn = &ctx->ir_base[use]; -#if IR_COMBO_COPY_PROPAGATION - IR_ASSERT((use_insn->op != IR_PHI) && "PHI must be already removed"); -#else - if (use_insn->op == IR_PHI) { - /* Convert PHI into COPY */ - ir_ref i, n = use_insn->inputs_count; - - for (i = 2; i <= n; i++) { - if (i != j + 1) { - ir_ref from = ir_insn_op(use_insn, i); - if (from > 0) { - ir_use_list_remove_one(ctx, from, use); - } - ir_insn_set_op(use_insn, i, IR_UNUSED); - } - } - use_insn->optx = IR_OPTX(IR_COPY, use_insn->type, 1); - use_insn->op1 = ir_insn_op(use_insn, j + 1); - ir_insn_set_op(use_insn, j + 1, IR_UNUSED); - ir_use_list_remove_one(ctx, ref, use); - p = &ctx->use_edges[use_list->refs + k]; - continue; - } -#endif - if (ir_op_flags[use_insn->op] & IR_OP_FLAG_CONTROL) { - IR_ASSERT(!next); - next = use; - next_insn = use_insn; - } else if (use_insn->op != IR_NOP) { - IR_ASSERT(use_insn->op1 == ref); - IR_ASSERT(use_insn->op == IR_VAR); - ir_ref region = prev; - while (!IR_IS_BB_START(ctx->ir_base[region].op)) { - region = ctx->ir_base[region].op1; - } - use_insn->op1 = region; - ir_use_list_add(ctx, region, use); - p = &ctx->use_edges[use_list->refs + k]; - } - k++; - p++; - } - } - IR_ASSERT(prev && next); - if (prev < next) { - /* remove MERGE and input END from double linked control list */ - next_insn->op1 = prev; - ir_use_list_replace_one(ctx, prev, input, next); - /* remove MERGE and input END instructions */ - ir_sccp_make_nop(ctx, ref); - ir_sccp_make_nop(ctx, input); - } else { - for (i = 2; i <= n; i++) { - ir_insn_set_op(insn, i, IR_UNUSED); - } - insn->op = IR_BEGIN; - insn->op1 = input; - input_insn->op = IR_END; - } - break; - } else { - for (i = 2; i <= n; i++) { - ir_insn_set_op(insn, i, IR_UNUSED); - } - insn->op = IR_BEGIN; - insn->op1 = input; - } + old_merge_inputs = insn->inputs_count; + new_merge_inputs = 0; + life_inputs = (old_merge_inputs - IR_BITSET_BITS) ? &holder : ir_bitset_malloc(old_merge_inputs + 1); + + for (i = 1; i <= old_merge_inputs; i++) { + ir_ref input = ir_insn_op(insn, i); + + if (input) { + new_merge_inputs++; + if (new_merge_inputs != i) { + ir_insn_set_op(insn, new_merge_inputs, input); } + ir_bitset_incl(life_inputs, i); } - } else { - n = insn->inputs_count; - i = 1; - life_inputs = ir_bitset_malloc(n + 1); - for (j = 1; j <= n; j++) { - ir_ref input = ir_insn_op(insn, j); + } - if (input) { - if (i != j) { - ir_insn_set_op(insn, i, input); - } - ir_bitset_incl(life_inputs, j); - i++; - } + if (new_merge_inputs == old_merge_inputs) { + /* All inputs are feasible */ + if (life_inputs != &holder) { + ir_mem_free(life_inputs); } - j = i; - while (j <= n) { - ir_insn_set_op(insn, j, IR_UNUSED); - j++; + return 0; + } + + for (i = new_merge_inputs + 1; i <= old_merge_inputs; i++) { + ir_insn_set_op(insn, i, IR_UNUSED); + } + + if (new_merge_inputs <= 1) { +#if 0 + if (new_merge_inputs == 1 + && insn->op == IR_LOOP_BEGIN + && insn->op1 > ref) { // TODO: check dominance instead of order + /* dead loop */ + ir_use_list_remove_one(ctx, insn->op1, ref); + insn->op1 = IR_UNUSED; + new_merge_inputs = 0; } - i--; - insn->inputs_count = i; +#endif + insn->optx = IR_OPTX(IR_BEGIN, IR_VOID, 1); + ir_bitqueue_add(worklist, ref); + } else { + insn->inputs_count = new_merge_inputs; + } - n++; - use_list = &ctx->use_lists[ref]; - if (use_list->count > 1) { - for (k = use_list->count, p = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) { - use = *p; - use_insn = &ctx->ir_base[use]; - if (use_insn->op == IR_PHI) { - i = 2; - for (j = 2; j <= n; j++) { - ir_ref input = ir_insn_op(use_insn, j); - - if (ir_bitset_in(life_inputs, j - 1)) { - IR_ASSERT(input); - if (i != j) { - ir_insn_set_op(use_insn, i, input); - } - i++; - } else if (!IR_IS_CONST_REF(input)) { - ir_use_list_remove_one(ctx, input, use); + /* Update PHIs */ + use_list = &ctx->use_lists[ref]; + if (use_list->count > 1) { + ir_ref use_count = 0; + ir_ref *q; + + for (i = 0, p = q = &ctx->use_edges[use_list->refs]; i < use_list->count; p++, i++) { + ir_ref use = *p; + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op == IR_PHI) { + ir_ref j, k; + + /* compress PHI */ + for (j = k = 1; j <= old_merge_inputs; j++) { + ir_ref input = ir_insn_op(use_insn, j + 1); + + if (ir_bitset_in(life_inputs, j)) { + IR_ASSERT(input); + if (k != j) { + ir_insn_set_op(use_insn, k + 1, input); } + k++; + } else if (input > 0) { + ir_use_list_remove_one(ctx, input, use); } - while (i <= n) { - ir_insn_set_op(use_insn, i, IR_UNUSED); - i++; - } - use_insn->inputs_count = insn->inputs_count + 1; } + while (k <= old_merge_inputs) { + k++; + ir_insn_set_op(use_insn, k, IR_UNUSED); + } + + if (new_merge_inputs == 0) { + /* remove PHI */ +#if 0 + use_insn->op1 = IR_UNUSED; + ir_iter_remove_insn(ctx, use, worklist); +#else + IR_ASSERT(0); +#endif + continue; + } else if (new_merge_inputs == 1) { + /* replace PHI by COPY */ + use_insn->optx = IR_OPTX(IR_COPY, use_insn->type, 1); + use_insn->op1 = use_insn->op2; + use_insn->op2 = IR_UNUSED; + ir_bitqueue_add(worklist, use); + continue; + } else { + use_insn->inputs_count = new_merge_inputs + 1; + } + } + if (p != q) { + *q = use; } + q++; + use_count++; } + for (i = use_count; i < use_list->count; q++, i++) { + *q = IR_UNUSED; + } + use_list->count = use_count; + } + + if (life_inputs != &holder) { ir_mem_free(life_inputs); } + + return 1; } static IR_NEVER_INLINE void ir_sccp_transform(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_bitqueue *iter_worklist) @@ -1105,7 +1068,7 @@ static IR_NEVER_INLINE void ir_sccp_transform(ir_ctx *ctx, ir_insn *_values, ir_ if (insn->op == IR_NOP) { /* already removed */ } else if (ir_op_flags[insn->op] & (IR_OP_FLAG_DATA|IR_OP_FLAG_MEM)) { - if (insn->op != IR_PARAM && (insn->op != IR_VAR || _values[insn->op1].op == IR_TOP)) { + if (insn->op != IR_PARAM) { ir_sccp_remove_insn(ctx, _values, i, iter_worklist); } } else { @@ -1137,7 +1100,7 @@ static IR_NEVER_INLINE void ir_sccp_transform(ir_ctx *ctx, ir_insn *_values, ir_ while ((i = ir_bitqueue_pop(worklist)) >= 0) { IR_ASSERT(_values[i].op == IR_MERGE); - ir_sccp_remove_unfeasible_merge_inputs(ctx, _values, i, _values[i].op1); + ir_sccp_remove_unfeasible_merge_inputs(ctx, i, &ctx->ir_base[i], iter_worklist); } } @@ -1261,7 +1224,7 @@ static void ir_iter_replace_insn(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bit ir_bitqueue_add(worklist, input); } else if (ctx->ir_base[input].op == IR_PHI && ctx->use_lists[input].count == 1) { /* try to optimize PHI into ABS/MIN/MAX/COND */ - ir_bitqueue_add(worklist, input); + ir_bitqueue_add(worklist, ctx->ir_base[input].op1); } } } @@ -1690,9 +1653,10 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use) return ref; } -static bool ir_may_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref) +static bool ir_may_promote_trunc(ir_ctx *ctx, ir_type type, ir_ref ref) { ir_insn *insn = &ctx->ir_base[ref]; + ir_ref *p, n, input; if (IR_IS_CONST_REF(ref)) { return !IR_IS_SYM_CONST(insn->op); @@ -1700,16 +1664,16 @@ static bool ir_may_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref) switch (insn->op) { case IR_ZEXT: case IR_SEXT: - return ctx->ir_base[insn->op1].type == type; + case IR_TRUNC: + return ctx->ir_base[insn->op1].type == type || ctx->use_lists[ref].count == 1; case IR_NEG: case IR_ABS: case IR_NOT: return ctx->use_lists[ref].count == 1 && - ir_may_promote_i2i(ctx, type, insn->op1); + ir_may_promote_trunc(ctx, type, insn->op1); case IR_ADD: case IR_SUB: case IR_MUL: -// case IR_DIV: case IR_MIN: case IR_MAX: case IR_OR: @@ -1717,8 +1681,41 @@ static bool ir_may_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref) case IR_XOR: case IR_SHL: return ctx->use_lists[ref].count == 1 && - ir_may_promote_i2i(ctx, type, insn->op1) && - ir_may_promote_i2i(ctx, type, insn->op2); + ir_may_promote_trunc(ctx, type, insn->op1) && + ir_may_promote_trunc(ctx, type, insn->op2); +// case IR_SHR: +// case IR_SAR: +// case IR_DIV: +// case IR_MOD: +// case IR_FP2INT: +// TODO: ??? + case IR_COND: + return ctx->use_lists[ref].count == 1 && + ir_may_promote_trunc(ctx, type, insn->op2) && + ir_may_promote_trunc(ctx, type, insn->op3); + case IR_PHI: + if (ctx->use_lists[ref].count != 1) { + ir_use_list *use_list = &ctx->use_lists[ref]; + ir_ref count = 0; + + for (p = &ctx->use_edges[use_list->refs], n = use_list->count; n > 0; p++, n--) { + if (*p != ref) { + if (count) { + return 0; + } + count = 1; + } + } + } + for (p = insn->ops + 1, n = insn->inputs_count - 1; n > 0; p++, n--) { + input = *p; + if (input != ref) { + if (!ir_may_promote_trunc(ctx, type, input)) { + return 0; + } + } + } + return 1; default: break; } @@ -1730,6 +1727,7 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) { ir_insn *insn = &ctx->ir_base[ref]; uint32_t count; + ir_ref *p, n, input; if (IR_IS_CONST_REF(ref)) { return ir_const(ctx, insn->val, type); @@ -1737,6 +1735,22 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) switch (insn->op) { case IR_ZEXT: case IR_SEXT: + case IR_TRUNC: + if (ctx->ir_base[insn->op1].type != type) { + ir_type src_type = ctx->ir_base[insn->op1].type; + if (ir_type_size[src_type] == ir_type_size[type]) { + insn->op = IR_BITCAST; + } else if (ir_type_size[src_type] > ir_type_size[type]) { + insn->op = IR_TRUNC; + } else { + if (insn->op != IR_SEXT && insn->op != IR_ZEXT) { + insn->op = IR_IS_TYPE_SIGNED(type) ? IR_SEXT : IR_ZEXT; + } + } + insn->type = type; + return ref; + } + count = ctx->use_lists[ref].count; ir_use_list_remove_all(ctx, ref, use); if (ctx->use_lists[ref].count == 0) { @@ -1768,7 +1782,6 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) case IR_ADD: case IR_SUB: case IR_MUL: -// case IR_DIV: case IR_MIN: case IR_MAX: case IR_OR: @@ -1783,6 +1796,30 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) } insn->type = type; return ref; +// case IR_DIV: +// case IR_MOD: +// case IR_SHR: +// case IR_SAR: +// case IR_FP2INT: +// TODO: ??? + case IR_COND: + if (insn->op2 == insn->op3) { + insn->op3 = insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref); + } else { + insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref); + insn->op3 = ir_promote_i2i(ctx, type, insn->op3, ref); + } + insn->type = type; + return ref; + case IR_PHI: + for (p = insn->ops + 1, n = insn->inputs_count - 1; n > 0; p++, n--) { + input = *p; + if (input != ref) { + *p = ir_promote_i2i(ctx, type, input, ref); + } + } + insn->type = type; + return ref; default: break; } @@ -1854,58 +1891,163 @@ static ir_ref ir_ext_ref(ir_ctx *ctx, ir_ref var_ref, ir_ref src_ref, ir_op op, return ref; } -static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bitqueue *worklist) +static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val) { - ir_type type = insn->type; - ir_op op = insn->op; - ir_ref ref = insn->op1; - ir_insn *phi_insn = &ctx->ir_base[ref]; - ir_insn *op_insn; - ir_use_list *use_list; - ir_ref n, *p, use, op_ref; + ir_insn *insn; + ir_ref n, *p, input, result, ctrl; - /* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */ - if (phi_insn->op != IR_PHI - || phi_insn->inputs_count != 3 /* (2 values) */ - || ctx->ir_base[phi_insn->op1].op != IR_LOOP_BEGIN) { - return 0; + if (IR_IS_CONST_REF(val)) { + return 1; /* IR_START */ } - op_ref = phi_insn->op3; - op_insn = &ctx->ir_base[op_ref]; - if ((op_insn->op != IR_ADD && op_insn->op != IR_SUB && op_insn->op != IR_MUL) - || (op_insn->op1 != ref && op_insn->op2 != ref) - || ctx->use_lists[op_ref].count != 1) { - return 0; + insn = &ctx->ir_base[val]; + if (ir_op_flags[insn->op] & (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM)) { + return val; } - /* Check if we may change the type of the induction variable */ - use_list = &ctx->use_lists[ref]; - n = use_list->count; - for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { - use = *p; - if (use == op_ref || use == ext_ref) { - continue; + IR_ASSERT(ir_op_flags[insn->op] & IR_OP_FLAG_DATA); + if (IR_OPND_KIND(ir_op_flags[insn->op], 1) & IR_OPND_CONTROL_DEP) { + return insn->op1; + } + + n = insn->inputs_count; + p = insn->ops + 1; + + result = 1; + for (; n > 0; p++, n--) { + input = *p; + ctrl = _ir_estimated_control(ctx, input); + if (ctrl > result) { // TODO: check dominance depth instead of order + result = ctrl; + } + } + return result; +} + +static bool ir_is_loop_invariant(ir_ctx *ctx, ir_ref ref, ir_ref loop) +{ + ref = _ir_estimated_control(ctx, ref); + return ref < loop; // TODO: check dominance instead of order +} + +static bool ir_is_cheaper_ext(ir_ctx *ctx, ir_ref ref, ir_ref loop, ir_ref ext_ref, ir_op op) +{ + if (IR_IS_CONST_REF(ref)) { + return 1; + } else { + ir_insn *insn = &ctx->ir_base[ref]; + + if (insn->op == IR_LOAD) { + if (ir_is_loop_invariant(ctx, ref, loop)) { + return 1; + } else { + /* ZEXT(LOAD(_, _)) costs the same as LOAD(_, _) */ + if (ctx->use_lists[ref].count == 2) { + return 1; + } else if (ctx->use_lists[ref].count == 3) { + ir_use_list *use_list = &ctx->use_lists[ref]; + ir_ref *p, n, use; + + for (p = &ctx->use_edges[use_list->refs], n = use_list->count; n > 0; p++, n--) { + use = *p; + if (use != ext_ref) { + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op != op + && (!(ir_op_flags[use_insn->op] & (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM)) + || use_insn->op1 != ref)) { + return 0; + } + } + } + return 1; + } + } + return 0; } else { - ir_insn *use_insn = &ctx->ir_base[use]; + return ir_is_loop_invariant(ctx, ref, loop); + } + } +} - if ((use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) - && (use_insn->op1 == ref || use_insn->op2 == ref)) { - continue; - } else if (use_insn->op == IR_IF) { +static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref phi_ref, ir_ref op_ref, ir_bitqueue *worklist) +{ + ir_op op = ctx->ir_base[ext_ref].op; + ir_type type = ctx->ir_base[ext_ref].type; + ir_insn *phi_insn; + ir_use_list *use_list; + ir_ref n, *p, use, ext_ref_2 = IR_UNUSED; + + /* Check if we may change the type of the induction variable */ + use_list = &ctx->use_lists[phi_ref]; + n = use_list->count; + if (n > 1) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { + use = *p; + if (use == op_ref || use == ext_ref) { continue; } else { - return 0; + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) { + if (use_insn->op1 == phi_ref) { + if (ir_is_cheaper_ext(ctx, use_insn->op2, ctx->ir_base[phi_ref].op1, ext_ref, op)) { + continue; + } + } else if (use_insn->op2 == phi_ref) { + if (ir_is_cheaper_ext(ctx, use_insn->op1, ctx->ir_base[phi_ref].op1, ext_ref, op)) { + continue; + } + } + return 0; + } else if (use_insn->op == IR_IF) { + continue; + } else if (!ext_ref_2 && use_insn->op == op && use_insn->type == type) { + ext_ref_2 = use; + continue; + } else { + return 0; + } } } } - phi_insn->type = insn->type; - op_insn->type = insn->type; + use_list = &ctx->use_lists[op_ref]; + n = use_list->count; + if (n > 1) { + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { + use = *p; + if (use == phi_ref || use == ext_ref) { + continue; + } else { + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) { + if (use_insn->op1 == phi_ref) { + if (ir_is_cheaper_ext(ctx, use_insn->op2, ctx->ir_base[phi_ref].op1, ext_ref, op)) { + continue; + } + } else if (use_insn->op2 == phi_ref) { + if (ir_is_cheaper_ext(ctx, use_insn->op1, ctx->ir_base[phi_ref].op1, ext_ref, op)) { + continue; + } + } + return 0; + } else if (use_insn->op == IR_IF) { + continue; + } else if (!ext_ref_2 && use_insn->op == op && use_insn->type == type) { + ext_ref_2 = use; + continue; + } else { + return 0; + } + } + } + } - for (n = 0; n < ctx->use_lists[ref].count; n++) { + for (n = 0; n < ctx->use_lists[phi_ref].count; n++) { /* "use_lists" may be reallocated by ir_ext_ref() */ - use = ctx->use_edges[ctx->use_lists[ref].refs + n]; + use = ctx->use_edges[ctx->use_lists[phi_ref].refs + n]; if (use == ext_ref) { continue; } else { @@ -1913,11 +2055,14 @@ static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bi if (use_insn->op == IR_IF) { continue; + } else if (use_insn->op == op) { + IR_ASSERT(ext_ref_2 == use); + continue; } IR_ASSERT(((use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) || use_insn->op == IR_ADD || use_insn->op == IR_SUB || use_insn->op == IR_MUL) - && (use_insn->op1 == ref || use_insn->op2 == ref)); - if (use_insn->op1 != ref) { + && (use_insn->op1 == phi_ref || use_insn->op2 == phi_ref)); + if (use_insn->op1 != phi_ref) { if (IR_IS_CONST_REF(use_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op1].op)) { ctx->ir_base[use].op1 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op1], op, type); @@ -1926,7 +2071,7 @@ static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bi } ir_bitqueue_add(worklist, use); } - if (use_insn->op2 != ref) { + if (use_insn->op2 != phi_ref) { if (IR_IS_CONST_REF(use_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op2].op)) { ctx->ir_base[use].op2 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op2], op, type); @@ -1938,19 +2083,108 @@ static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bi } } - ir_iter_replace_insn(ctx, ext_ref, ref, worklist); + if (ctx->use_lists[op_ref].count > 1) { + for (n = 0; n < ctx->use_lists[op_ref].count; n++) { + /* "use_lists" may be reallocated by ir_ext_ref() */ + use = ctx->use_edges[ctx->use_lists[op_ref].refs + n]; + if (use == ext_ref || use == phi_ref) { + continue; + } else { + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op == IR_IF) { + continue; + } else if (use_insn->op == op) { + IR_ASSERT(ext_ref_2 == use); + continue; + } + IR_ASSERT(use_insn->op >= IR_EQ && use_insn->op <= IR_UGT); + if (use_insn->op1 != op_ref) { + if (IR_IS_CONST_REF(use_insn->op1) + && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op1].op)) { + ctx->ir_base[use].op1 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op1], op, type); + } else { + ctx->ir_base[use].op1 = ir_ext_ref(ctx, use, use_insn->op1, op, type, worklist); + } + ir_bitqueue_add(worklist, use); + } + if (use_insn->op2 != op_ref) { + if (IR_IS_CONST_REF(use_insn->op2) + && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op2].op)) { + ctx->ir_base[use].op2 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op2], op, type); + } else { + ctx->ir_base[use].op2 = ir_ext_ref(ctx, use, use_insn->op2, op, type, worklist); + } + ir_bitqueue_add(worklist, use); + } + } + } + } - phi_insn = &ctx->ir_base[ref]; + ir_iter_replace_insn(ctx, ext_ref, ctx->ir_base[ext_ref].op1, worklist); + + if (ext_ref_2) { + ir_iter_replace_insn(ctx, ext_ref_2, ctx->ir_base[ext_ref_2].op1, worklist); + } + + ctx->ir_base[op_ref].type = type; + + phi_insn = &ctx->ir_base[phi_ref]; + phi_insn->type = type; if (IR_IS_CONST_REF(phi_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[phi_insn->op2].op)) { - ctx->ir_base[ref].op2 = ir_ext_const(ctx, &ctx->ir_base[phi_insn->op2], op, type); + ctx->ir_base[phi_ref].op2 = ir_ext_const(ctx, &ctx->ir_base[phi_insn->op2], op, type); } else { - ctx->ir_base[ref].op2 = ir_ext_ref(ctx, ref, phi_insn->op2, op, type, worklist); + ctx->ir_base[phi_ref].op2 = ir_ext_ref(ctx, phi_ref, phi_insn->op2, op, type, worklist); } return 1; } +static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bitqueue *worklist) + { + ir_ref ref = insn->op1; + + /* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */ + insn = &ctx->ir_base[ref]; + if (insn->op == IR_PHI + && insn->inputs_count == 3 /* (2 values) */ + && ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN) { + ir_ref op_ref = insn->op3; + ir_insn *op_insn = &ctx->ir_base[op_ref]; + + if (op_insn->op == IR_ADD || op_insn->op == IR_SUB || op_insn->op == IR_MUL) { + if (op_insn->op1 == ref) { + if (ir_is_loop_invariant(ctx, op_insn->op2, insn->op1)) { + return ir_try_promote_induction_var_ext(ctx, ext_ref, ref, op_ref, worklist); + } + } else if (op_insn->op2 == ref) { + if (ir_is_loop_invariant(ctx, op_insn->op1, insn->op1)) { + return ir_try_promote_induction_var_ext(ctx, ext_ref, ref, op_ref, worklist); + } + } + } + } else if (insn->op == IR_ADD || insn->op == IR_SUB || insn->op == IR_MUL) { + if (!IR_IS_CONST_REF(insn->op1) + && ctx->ir_base[insn->op1].op == IR_PHI + && ctx->ir_base[insn->op1].inputs_count == 3 /* (2 values) */ + && ctx->ir_base[insn->op1].op3 == ref + && ctx->ir_base[ctx->ir_base[insn->op1].op1].op == IR_LOOP_BEGIN + && ir_is_loop_invariant(ctx, insn->op2, ctx->ir_base[insn->op1].op1)) { + return ir_try_promote_induction_var_ext(ctx, ext_ref, insn->op1, ref, worklist); + } else if (!IR_IS_CONST_REF(insn->op2) + && ctx->ir_base[insn->op2].op == IR_PHI + && ctx->ir_base[insn->op2].inputs_count == 3 /* (2 values) */ + && ctx->ir_base[insn->op2].op3 == ref + && ctx->ir_base[ctx->ir_base[insn->op2].op1].op == IR_LOOP_BEGIN + && ir_is_loop_invariant(ctx, insn->op1, ctx->ir_base[insn->op2].op1)) { + return ir_try_promote_induction_var_ext(ctx, ext_ref, insn->op2, ref, worklist); + } + } + + return 0; +} + static void ir_get_true_false_refs(const ir_ctx *ctx, ir_ref if_ref, ir_ref *if_true_ref, ir_ref *if_false_ref) { ir_use_list *use_list = &ctx->use_lists[if_ref]; @@ -1969,11 +2203,47 @@ static void ir_get_true_false_refs(const ir_ctx *ctx, ir_ref if_ref, ir_ref *if_ } } -static void ir_merge_blocks(ir_ctx *ctx, ir_ref end, ir_ref begin, ir_bitqueue *worklist2) +static void ir_merge_blocks(ir_ctx *ctx, ir_ref end, ir_ref begin, ir_bitqueue *worklist) { ir_ref prev, next; ir_use_list *use_list; + if (ctx->use_lists[begin].count > 1) { + ir_ref *p, n, i, use; + ir_insn *use_insn; + ir_ref region = end; + ir_ref next = IR_UNUSED; + + while (!IR_IS_BB_START(ctx->ir_base[region].op)) { + region = ctx->ir_base[region].op1; + } + + use_list = &ctx->use_lists[begin]; + n = use_list->count; + for (p = &ctx->use_edges[use_list->refs], i = 0; i < n; p++, i++) { + use = *p; + use_insn = &ctx->ir_base[use]; + if (ir_op_flags[use_insn->op] & IR_OP_FLAG_CONTROL) { + IR_ASSERT(!next); + next = use; + } else { + IR_ASSERT(use_insn->op == IR_VAR); + IR_ASSERT(use_insn->op1 == begin); + use_insn->op1 = region; + if (ir_use_list_add(ctx, region, use)) { + /* restore after reallocation */ + use_list = &ctx->use_lists[begin]; + n = use_list->count; + p = &ctx->use_edges[use_list->refs + i]; + } + } + } + + IR_ASSERT(next); + ctx->use_edges[use_list->refs] = next; + use_list->count = 1; + } + IR_ASSERT(ctx->ir_base[begin].op == IR_BEGIN); IR_ASSERT(ctx->ir_base[end].op == IR_END); IR_ASSERT(ctx->ir_base[begin].op1 == end); @@ -1994,7 +2264,7 @@ static void ir_merge_blocks(ir_ctx *ctx, ir_ref end, ir_ref begin, ir_bitqueue * ir_use_list_replace_one(ctx, prev, end, next); if (ctx->ir_base[prev].op == IR_BEGIN || ctx->ir_base[prev].op == IR_MERGE) { - ir_bitqueue_add(worklist2, prev); + ir_bitqueue_add(worklist, prev); } } @@ -2950,6 +3220,68 @@ static void ir_iter_optimize_merge(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge } } +static ir_ref ir_find_ext_use(ir_ctx *ctx, ir_ref ref) +{ + ir_use_list *use_list = &ctx->use_lists[ref]; + ir_ref *p, n, use; + ir_insn *use_insn; + + for (p = &ctx->use_edges[use_list->refs], n = use_list->count; n > 0; p++, n--) { + use = *p; + use_insn = &ctx->ir_base[use]; + if (use_insn->op == IR_SEXT || use_insn->op == IR_ZEXT) { + return use; + } + } + return IR_UNUSED; +} + +static void ir_iter_optimize_induction_var(ir_ctx *ctx, ir_ref phi_ref, ir_ref op_ref, ir_bitqueue *worklist) +{ + ir_ref ext_ref; + + ext_ref = ir_find_ext_use(ctx, phi_ref); + if (!ext_ref) { + ext_ref = ir_find_ext_use(ctx, op_ref); + } + if (ext_ref) { + ir_try_promote_induction_var_ext(ctx, ext_ref, phi_ref, op_ref, worklist); + } +} + +static void ir_iter_optimize_loop(ir_ctx *ctx, ir_ref loop_ref, ir_insn *loop, ir_bitqueue *worklist) +{ + ir_ref n; + + if (loop->inputs_count != 2 || ctx->use_lists[loop_ref].count <= 1) { + return; + } + + /* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */ + for (n = 0; n < ctx->use_lists[loop_ref].count; n++) { + /* "use_lists" may be reallocated by ir_ext_ref() */ + ir_ref use = ctx->use_edges[ctx->use_lists[loop_ref].refs + n]; + ir_insn *use_insn = &ctx->ir_base[use]; + + if (use_insn->op == IR_PHI) { + ir_ref op_ref = use_insn->op3; + ir_insn *op_insn = &ctx->ir_base[op_ref]; + + if (op_insn->op == IR_ADD || op_insn->op == IR_SUB || op_insn->op == IR_MUL) { + if (op_insn->op1 == use) { + if (ir_is_loop_invariant(ctx, op_insn->op2, loop_ref)) { + ir_iter_optimize_induction_var(ctx, use, op_ref, worklist); + } + } else if (op_insn->op2 == use) { + if (ir_is_loop_invariant(ctx, op_insn->op1, loop_ref)) { + ir_iter_optimize_induction_var(ctx, use, op_ref, worklist); + } + } + } + } + } +} + static ir_ref ir_iter_optimize_condition(ir_ctx *ctx, ir_ref control, ir_ref condition, bool *swap) { ir_insn *condition_insn = &ctx->ir_base[condition]; @@ -3042,6 +3374,7 @@ static void ir_iter_optimize_if(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqu insn->optx = IR_OPTX(IR_END, IR_VOID, 1); if (!IR_IS_CONST_REF(insn->op2)) { ir_use_list_remove_one(ctx, insn->op2, ref); + ir_bitqueue_add(worklist, insn->op2); } insn->op2 = IR_UNUSED; @@ -3168,7 +3501,7 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist) } goto folding; case IR_TRUNC: - if (ir_may_promote_i2i(ctx, insn->type, insn->op1)) { + if (ir_may_promote_trunc(ctx, insn->type, insn->op1)) { ir_ref ref = ir_promote_i2i(ctx, insn->type, insn->op1, i); insn->op1 = ref; ir_iter_replace_insn(ctx, i, ref, worklist); @@ -3193,12 +3526,13 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist) if (!(ctx->flags & IR_OPT_CFG)) { /* pass */ } else if (insn->op == IR_BEGIN) { - if (ctx->ir_base[insn->op1].op == IR_END - && ctx->use_lists[i].count == 1) { + if (insn->op1 && ctx->ir_base[insn->op1].op == IR_END) { ir_merge_blocks(ctx, insn->op1, i, worklist); } } else if (insn->op == IR_MERGE) { ir_iter_optimize_merge(ctx, i, insn, worklist); + } else if (insn->op == IR_LOOP_BEGIN) { + ir_iter_optimize_loop(ctx, i, insn, worklist); } } else if (ir_is_dead_load(ctx, i)) { ir_ref next; From 69480be12afb4040c6dd9275b7836231cdd6f6bb Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 12 Mar 2025 07:48:05 +0100 Subject: [PATCH 078/503] Relax test expectation for pcre2lib 10.45 Using e92848789acd8aa5cf32fedb519ba9378ac64e02 Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- ext/pcre/tests/bug75457.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pcre/tests/bug75457.phpt b/ext/pcre/tests/bug75457.phpt index ee5ab162f8a6c..1401b25ff6fb7 100644 --- a/ext/pcre/tests/bug75457.phpt +++ b/ext/pcre/tests/bug75457.phpt @@ -6,5 +6,5 @@ $pattern = "/(((?(?C)0?=))(?!()0|.(?0)0)())/"; var_dump(preg_match($pattern, "hello")); ?> --EXPECTF-- -Warning: preg_match(): Compilation failed: assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d +Warning: preg_match(): Compilation failed:%r( atomic|)%r assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d bool(false) From 0d10f7bfe55856e0b545bc87f523ee3c3f4b54aa Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 13 Mar 2025 10:59:26 +0100 Subject: [PATCH 079/503] Remove OpenSSL 1.0.2 related code (#18032) This also removes old LibreSSL checks as minimum that compiles is 3.5.0 --- ext/openssl/openssl_backend_v1.c | 145 +------------------------------ ext/openssl/php_openssl.h | 10 +-- 2 files changed, 2 insertions(+), 153 deletions(-) diff --git a/ext/openssl/openssl_backend_v1.c b/ext/openssl/openssl_backend_v1.c index e00b0962fd8d7..dfdb7b014060a 100644 --- a/ext/openssl/openssl_backend_v1.c +++ b/ext/openssl/openssl_backend_v1.c @@ -27,159 +27,16 @@ #include #endif -/* OpenSSL compatibility functions and macros */ -#if PHP_OPENSSL_API_VERSION < 0x10100 - -#define EVP_PKEY_get0_RSA(_pkey) _pkey->pkey.rsa -#define EVP_PKEY_get0_DH(_pkey) _pkey->pkey.dh -#define EVP_PKEY_get0_DSA(_pkey) _pkey->pkey.dsa -#define EVP_PKEY_get0_EC_KEY(_pkey) _pkey->pkey.ec - -static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) -{ - r->n = n; - r->e = e; - r->d = d; - - return 1; -} - -static int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) -{ - r->p = p; - r->q = q; - - return 1; -} - -static int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) -{ - r->dmp1 = dmp1; - r->dmq1 = dmq1; - r->iqmp = iqmp; - - return 1; -} - -static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -{ - *n = r->n; - *e = r->e; - *d = r->d; -} - -static void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -{ - *p = r->p; - *q = r->q; -} - -static void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) -{ - *dmp1 = r->dmp1; - *dmq1 = r->dmq1; - *iqmp = r->iqmp; -} - -static void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -{ - *p = dh->p; - *q = dh->q; - *g = dh->g; -} - -static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) -{ - dh->p = p; - dh->q = q; - dh->g = g; - - return 1; -} - -static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) -{ - *pub_key = dh->pub_key; - *priv_key = dh->priv_key; -} - -static int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) -{ - dh->pub_key = pub_key; - dh->priv_key = priv_key; - - return 1; -} - -static void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -{ - *p = d->p; - *q = d->q; - *g = d->g; -} - -int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) -{ - d->p = p; - d->q = q; - d->g = g; - - return 1; -} - -static void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) -{ - *pub_key = d->pub_key; - *priv_key = d->priv_key; -} - -int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) -{ - d->pub_key = pub_key; - d->priv_key = priv_key; - - return 1; -} - -static const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) -{ - return M_ASN1_STRING_data(asn1); -} - -static int EVP_PKEY_up_ref(EVP_PKEY *pkey) -{ - return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); -} - -#if PHP_OPENSSL_API_VERSION < 0x10002 - -static int X509_get_signature_nid(const X509 *x) -{ - return OBJ_obj2nid(x->sig_alg->algorithm); -} - -#endif - -#define OpenSSL_version SSLeay_version -#define OPENSSL_VERSION SSLEAY_VERSION -#define X509_getm_notBefore X509_get_notBefore -#define X509_getm_notAfter X509_get_notAfter -#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_cleanup - -#endif - void php_openssl_backend_shutdown(void) { - #ifdef LIBRESSL_VERSION_NUMBER +#ifdef LIBRESSL_VERSION_NUMBER EVP_cleanup(); /* prevent accessing locking callback from unloaded extension */ CRYPTO_set_locking_callback(NULL); -#ifndef OPENSSL_NO_ENGINE /* Free engine list initialized by OPENSSL_config */ ENGINE_cleanup(); -#endif /* free allocated error strings */ ERR_free_strings(); diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 3f408926bc493..bc101539d1b1e 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -26,23 +26,15 @@ extern zend_module_entry openssl_module_entry; #define PHP_OPENSSL_VERSION PHP_VERSION #include -#ifdef LIBRESSL_VERSION_NUMBER -/* LibreSSL version check */ -#if LIBRESSL_VERSION_NUMBER < 0x20700000L -#define PHP_OPENSSL_API_VERSION 0x10001 -#else -#define PHP_OPENSSL_API_VERSION 0x10100 -#endif -#else /* OpenSSL version check */ #if OPENSSL_VERSION_NUMBER < 0x30000000L +/* This includes LibreSSL that defines version 0x20000000L */ #define PHP_OPENSSL_API_VERSION 0x10100 #elif OPENSSL_VERSION_NUMBER < 0x30200000L #define PHP_OPENSSL_API_VERSION 0x30000 #else #define PHP_OPENSSL_API_VERSION 0x30200 #endif -#endif #define OPENSSL_RAW_DATA 1 #define OPENSSL_ZERO_PADDING 2 From 3f3ac4de25486fabae99d1d648583d4bd852a592 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Thu, 13 Mar 2025 13:14:31 +0100 Subject: [PATCH 080/503] [skip ci] Remove wrappers comments in session ext (#18017) --- ext/session/mod_user_class.c | 14 -- ext/session/session.c | 281 ++++++++++++----------------------- 2 files changed, 92 insertions(+), 203 deletions(-) diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index 853db659887be..22be2cd151949 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -34,7 +34,6 @@ RETURN_FALSE; \ } -/* {{{ Wraps the old open handler */ PHP_METHOD(SessionHandler, open) { char *save_path = NULL, *session_name = NULL; @@ -60,9 +59,7 @@ PHP_METHOD(SessionHandler, open) RETURN_BOOL(SUCCESS == ret); } -/* }}} */ -/* {{{ Wraps the old close handler */ PHP_METHOD(SessionHandler, close) { zend_result ret; @@ -84,9 +81,7 @@ PHP_METHOD(SessionHandler, close) RETURN_BOOL(SUCCESS == ret); } -/* }}} */ -/* {{{ Wraps the old read handler */ PHP_METHOD(SessionHandler, read) { zend_string *val; @@ -104,9 +99,7 @@ PHP_METHOD(SessionHandler, read) RETURN_STR(val); } -/* }}} */ -/* {{{ Wraps the old write handler */ PHP_METHOD(SessionHandler, write) { zend_string *key, *val; @@ -119,9 +112,7 @@ PHP_METHOD(SessionHandler, write) RETURN_BOOL(SUCCESS == PS(default_mod)->s_write(&PS(mod_data), key, val, PS(gc_maxlifetime))); } -/* }}} */ -/* {{{ Wraps the old destroy handler */ PHP_METHOD(SessionHandler, destroy) { zend_string *key; @@ -134,9 +125,7 @@ PHP_METHOD(SessionHandler, destroy) RETURN_BOOL(SUCCESS == PS(default_mod)->s_destroy(&PS(mod_data), key)); } -/* }}} */ -/* {{{ Wraps the old gc handler */ PHP_METHOD(SessionHandler, gc) { zend_long maxlifetime; @@ -153,9 +142,7 @@ PHP_METHOD(SessionHandler, gc) } RETURN_LONG(nrdels); } -/* }}} */ -/* {{{ Wraps the old create_sid handler */ PHP_METHOD(SessionHandler, create_sid) { zend_string *id; @@ -170,4 +157,3 @@ PHP_METHOD(SessionHandler, create_sid) RETURN_STR(id); } -/* }}} */ diff --git a/ext/session/session.c b/ext/session/session.c index ae6576856e48e..fd877483c0a6f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -105,7 +105,7 @@ static zend_result php_session_abort(void); static int my_module_number = 0; /* Dispatched by RINIT and by php_session_destroy */ -static inline void php_rinit_session_globals(void) /* {{{ */ +static inline void php_rinit_session_globals(void) { /* Do NOT init PS(mod_user_names) here! */ /* TODO: These could be moved to MINIT and removed. These should be initialized by php_rshutdown_session_globals() always when execution is finished. */ @@ -120,9 +120,8 @@ static inline void php_rinit_session_globals(void) /* {{{ */ PS(module_number) = my_module_number; ZVAL_UNDEF(&PS(http_session_vars)); } -/* }}} */ -static inline void php_session_headers_already_sent_error(int severity, const char *message) { /* {{{ */ +static inline void php_session_headers_already_sent_error(int severity, const char *message) { const char *output_start_filename = php_output_get_start_filename(); int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename != NULL) { @@ -131,9 +130,8 @@ static inline void php_session_headers_already_sent_error(int severity, const ch php_error_docref(NULL, severity, "%s", message); } } -/* }}} */ -static inline void php_session_session_already_started_error(int severity, const char *message) { /* {{{ */ +static inline void php_session_session_already_started_error(int severity, const char *message) { if (PS(session_started_filename) != NULL) { php_error_docref(NULL, severity, "%s (started from %s on line %"PRIu32")", message, ZSTR_VAL(PS(session_started_filename)), PS(session_started_lineno)); } else if (PS(auto_start)) { @@ -143,9 +141,8 @@ static inline void php_session_session_already_started_error(int severity, const php_error_docref(NULL, severity, "%s", message); } } -/* }}} */ -static inline void php_session_cleanup_filename(void) /* {{{ */ +static inline void php_session_cleanup_filename(void) { if (PS(session_started_filename)) { zend_string_release(PS(session_started_filename)); @@ -153,10 +150,9 @@ static inline void php_session_cleanup_filename(void) /* {{{ */ PS(session_started_lineno) = 0; } } -/* }}} */ /* Dispatched by RSHUTDOWN and by php_session_destroy */ -static void php_rshutdown_session_globals(void) /* {{{ */ +static void php_rshutdown_session_globals(void) { /* Do NOT destroy PS(mod_user_names) here! */ if (!Z_ISUNDEF(PS(http_session_vars))) { @@ -189,9 +185,8 @@ static void php_rshutdown_session_globals(void) /* {{{ */ /* Set session status to prevent error while restoring save handler INI value. */ PS(session_status) = php_session_none; } -/* }}} */ -PHPAPI zend_result php_session_destroy(void) /* {{{ */ +PHPAPI zend_result php_session_destroy(void) { zend_result retval = SUCCESS; @@ -212,9 +207,8 @@ PHPAPI zend_result php_session_destroy(void) /* {{{ */ return retval; } -/* }}} */ -PHPAPI void php_add_session_var(zend_string *name) /* {{{ */ +PHPAPI void php_add_session_var(zend_string *name) { IF_SESSION_VARS() { zval *sess_var = Z_REFVAL(PS(http_session_vars)); @@ -226,9 +220,8 @@ PHPAPI void php_add_session_var(zend_string *name) /* {{{ */ } } } -/* }}} */ -PHPAPI zval* php_set_session_var(zend_string *name, zval *state_val, php_unserialize_data_t *var_hash) /* {{{ */ +PHPAPI zval* php_set_session_var(zend_string *name, zval *state_val, php_unserialize_data_t *var_hash) { IF_SESSION_VARS() { zval *sess_var = Z_REFVAL(PS(http_session_vars)); @@ -237,16 +230,14 @@ PHPAPI zval* php_set_session_var(zend_string *name, zval *state_val, php_unseria } return NULL; } -/* }}} */ -PHPAPI zval* php_get_session_var(zend_string *name) /* {{{ */ +PHPAPI zval* php_get_session_var(zend_string *name) { IF_SESSION_VARS() { return zend_hash_find(Z_ARRVAL_P(Z_REFVAL(PS(http_session_vars))), name); } return NULL; } -/* }}} */ PHPAPI zval* php_get_session_var_str(const char *name, size_t name_len) { @@ -256,7 +247,7 @@ PHPAPI zval* php_get_session_var_str(const char *name, size_t name_len) return NULL; } -static void php_session_track_init(void) /* {{{ */ +static void php_session_track_init(void) { zval session_vars; zend_string *var_name = ZSTR_INIT_LITERAL("_SESSION", 0); @@ -273,9 +264,8 @@ static void php_session_track_init(void) /* {{{ */ zend_hash_update_ind(&EG(symbol_table), var_name, &PS(http_session_vars)); zend_string_release_ex(var_name, 0); } -/* }}} */ -static zend_string *php_session_encode(void) /* {{{ */ +static zend_string *php_session_encode(void) { IF_SESSION_VARS() { ZEND_ASSERT(PS(serializer)); @@ -285,7 +275,6 @@ static zend_string *php_session_encode(void) /* {{{ */ } return NULL; } -/* }}} */ static ZEND_COLD void php_session_cancel_decode(void) { @@ -294,7 +283,7 @@ static ZEND_COLD void php_session_cancel_decode(void) php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed"); } -static zend_result php_session_decode(zend_string *data) /* {{{ */ +static zend_result php_session_decode(zend_string *data) { ZEND_ASSERT(PS(serializer)); zend_result result = SUCCESS; @@ -309,7 +298,6 @@ static zend_result php_session_decode(zend_string *data) /* {{{ */ } zend_end_try(); return result; } -/* }}} */ /* * Note that we cannot use the BASE64 alphabet here, because @@ -319,7 +307,7 @@ static zend_result php_session_decode(zend_string *data) /* {{{ */ static const char hexconvtab[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-"; -static void bin_to_readable(unsigned char *in, size_t inlen, char *out, size_t outlen, char nbits) /* {{{ */ +static void bin_to_readable(unsigned char *in, size_t inlen, char *out, size_t outlen, char nbits) { unsigned char *p, *q; unsigned short w; @@ -353,9 +341,8 @@ static void bin_to_readable(unsigned char *in, size_t inlen, char *out, size_t o *out = '\0'; } -/* }}} */ -PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */ +PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS) { unsigned char rbuf[PS_MAX_SID_LENGTH]; zend_string *outid; @@ -374,12 +361,11 @@ PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */ return outid; } -/* }}} */ /* Default session id char validation function allowed by ps_modules. * If you change the logic here, please also update the error message in * ps_modules appropriately */ -PHPAPI zend_result php_session_valid_key(const char *key) /* {{{ */ +PHPAPI zend_result php_session_valid_key(const char *key) { size_t len; const char *p; @@ -406,10 +392,9 @@ PHPAPI zend_result php_session_valid_key(const char *key) /* {{{ */ return SUCCESS; } -/* }}} */ -static zend_long php_session_gc(bool immediate) /* {{{ */ +static zend_long php_session_gc(bool immediate) { zend_long num = -1; bool collect = immediate; @@ -425,9 +410,9 @@ static zend_long php_session_gc(bool immediate) /* {{{ */ } } return num; -} /* }}} */ +} -static zend_result php_session_initialize(void) /* {{{ */ +static zend_result php_session_initialize(void) { zend_string *val = NULL; @@ -520,9 +505,8 @@ static zend_result php_session_initialize(void) /* {{{ */ } return SUCCESS; } -/* }}} */ -static void php_session_save_current_state(int write) /* {{{ */ +static void php_session_save_current_state(int write) { zend_result ret = FAILURE; @@ -578,9 +562,8 @@ static void php_session_save_current_state(int write) /* {{{ */ PS(mod)->s_close(&PS(mod_data)); } } -/* }}} */ -static void php_session_normalize_vars(void) /* {{{ */ +static void php_session_normalize_vars(void) { PS_ENCODE_VARS; @@ -594,13 +577,12 @@ static void php_session_normalize_vars(void) /* {{{ */ ); } } -/* }}} */ /* ************************* * INI Settings/Handlers * ************************* */ -static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */ +static PHP_INI_MH(OnUpdateSaveHandler) { const ps_module *tmp; int err_type = E_ERROR; @@ -634,9 +616,8 @@ static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_INI_MH(OnUpdateSerializer) /* {{{ */ +static PHP_INI_MH(OnUpdateSerializer) { const ps_serializer *tmp; @@ -664,9 +645,8 @@ static PHP_INI_MH(OnUpdateSerializer) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */ +static PHP_INI_MH(OnUpdateSaveDir) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; @@ -697,10 +677,9 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */ return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ -static PHP_INI_MH(OnUpdateName) /* {{{ */ +static PHP_INI_MH(OnUpdateName) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; @@ -729,10 +708,9 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */ return OnUpdateStringUnempty(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ -static PHP_INI_MH(OnUpdateCookieLifetime) /* {{{ */ +static PHP_INI_MH(OnUpdateCookieLifetime) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; @@ -751,37 +729,32 @@ static PHP_INI_MH(OnUpdateCookieLifetime) /* {{{ */ } return OnUpdateLongGEZero(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ -static PHP_INI_MH(OnUpdateSessionLong) /* {{{ */ +static PHP_INI_MH(OnUpdateSessionLong) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; return OnUpdateLong(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ - -static PHP_INI_MH(OnUpdateSessionString) /* {{{ */ +static PHP_INI_MH(OnUpdateSessionString) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ -static PHP_INI_MH(OnUpdateSessionBool) /* {{{ */ +static PHP_INI_MH(OnUpdateSessionBool) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* }}} */ -static PHP_INI_MH(OnUpdateSidLength) /* {{{ */ +static PHP_INI_MH(OnUpdateSidLength) { zend_long val; char *endptr = NULL; @@ -802,9 +775,8 @@ static PHP_INI_MH(OnUpdateSidLength) /* {{{ */ php_error_docref(NULL, E_WARNING, "session.configuration \"session.sid_length\" must be between 22 and 256"); return FAILURE; } -/* }}} */ -static PHP_INI_MH(OnUpdateSidBits) /* {{{ */ +static PHP_INI_MH(OnUpdateSidBits) { zend_long val; char *endptr = NULL; @@ -825,9 +797,8 @@ static PHP_INI_MH(OnUpdateSidBits) /* {{{ */ php_error_docref(NULL, E_WARNING, "session.configuration \"session.sid_bits_per_character\" must be between 4 and 6"); return FAILURE; } -/* }}} */ -static PHP_INI_MH(OnUpdateSessionGcProbability) /* {{{ */ +static PHP_INI_MH(OnUpdateSessionGcProbability) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; @@ -844,9 +815,8 @@ static PHP_INI_MH(OnUpdateSessionGcProbability) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_INI_MH(OnUpdateSessionDivisor) /* {{{ */ +static PHP_INI_MH(OnUpdateSessionDivisor) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; @@ -863,9 +833,8 @@ static PHP_INI_MH(OnUpdateSessionDivisor) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ +static PHP_INI_MH(OnUpdateRfc1867Freq) { int tmp = ZEND_ATOL(ZSTR_VAL(new_value)); if(tmp < 0) { @@ -882,7 +851,7 @@ static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ PS(rfc1867_freq) = tmp; } return SUCCESS; -} /* }}} */ +} static PHP_INI_MH(OnUpdateUseOnlyCookies) { @@ -918,7 +887,6 @@ static PHP_INI_MH(OnUpdateRefererCheck) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -/* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir, save_path, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals) @@ -961,12 +929,11 @@ PHP_INI_BEGIN() /* Commented out until future discussion */ /* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */ PHP_INI_END() -/* }}} */ /* *************** * Serializers * *************** */ -PS_SERIALIZER_ENCODE_FUNC(php_serialize) /* {{{ */ +PS_SERIALIZER_ENCODE_FUNC(php_serialize) { smart_str buf = {0}; php_serialize_data_t var_hash; @@ -978,9 +945,8 @@ PS_SERIALIZER_ENCODE_FUNC(php_serialize) /* {{{ */ } return buf.s; } -/* }}} */ -PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */ +PS_SERIALIZER_DECODE_FUNC(php_serialize) { const char *endptr = val + vallen; zval session_vars; @@ -1010,13 +976,12 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */ zend_string_release_ex(var_name, 0); return result || !vallen ? SUCCESS : FAILURE; } -/* }}} */ #define PS_BIN_NR_OF_BITS 8 #define PS_BIN_UNDEF (1<<(PS_BIN_NR_OF_BITS-1)) #define PS_BIN_MAX (PS_BIN_UNDEF-1) -PS_SERIALIZER_ENCODE_FUNC(php_binary) /* {{{ */ +PS_SERIALIZER_ENCODE_FUNC(php_binary) { smart_str buf = {0}; php_serialize_data_t var_hash; @@ -1036,9 +1001,8 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary) /* {{{ */ return buf.s; } -/* }}} */ -PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ +PS_SERIALIZER_DECODE_FUNC(php_binary) { const char *p; const char *endptr = val + vallen; @@ -1077,11 +1041,10 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ return SUCCESS; } -/* }}} */ #define PS_DELIMITER '|' -PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */ +PS_SERIALIZER_ENCODE_FUNC(php) { smart_str buf = {0}; php_serialize_data_t var_hash; @@ -1111,9 +1074,8 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */ PHP_VAR_SERIALIZE_DESTROY(var_hash); return buf.s; } -/* }}} */ -PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ +PS_SERIALIZER_DECODE_FUNC(php) { const char *p, *q; const char *endptr = val + vallen; @@ -1160,7 +1122,6 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ return retval; } -/* }}} */ #define MAX_SERIALIZERS 32 #define PREDEFINED_SERIALIZERS 3 @@ -1171,7 +1132,7 @@ static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PS_SERIALIZER_ENTRY(php_binary) }; -PHPAPI zend_result php_session_register_serializer(const char *name, zend_string *(*encode)(PS_SERIALIZER_ENCODE_ARGS), zend_result (*decode)(PS_SERIALIZER_DECODE_ARGS)) /* {{{ */ +PHPAPI zend_result php_session_register_serializer(const char *name, zend_string *(*encode)(PS_SERIALIZER_ENCODE_ARGS), zend_result (*decode)(PS_SERIALIZER_DECODE_ARGS)) { zend_result ret = FAILURE; @@ -1187,7 +1148,6 @@ PHPAPI zend_result php_session_register_serializer(const char *name, zend_string } return ret; } -/* }}} */ /* ******************* * Storage Modules * @@ -1201,7 +1161,7 @@ static const ps_module *ps_modules[MAX_MODULES + 1] = { ps_user_ptr }; -PHPAPI zend_result php_session_register_module(const ps_module *ptr) /* {{{ */ +PHPAPI zend_result php_session_register_module(const ps_module *ptr) { int ret = FAILURE; @@ -1214,7 +1174,6 @@ PHPAPI zend_result php_session_register_module(const ps_module *ptr) /* {{{ */ } return ret; } -/* }}} */ /* Dummy PS module function */ /* We consider any ID valid (thus also implying that a session with such an ID exists), @@ -1253,7 +1212,7 @@ static const char *week_days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; -static inline void strcpy_gmt(char *ubuf, time_t *when) /* {{{ */ +static inline void strcpy_gmt(char *ubuf, time_t *when) { char buf[MAX_STR]; struct tm tm, *res; @@ -1274,9 +1233,8 @@ static inline void strcpy_gmt(char *ubuf, time_t *when) /* {{{ */ memcpy(ubuf, buf, n); ubuf[n] = '\0'; } -/* }}} */ -static inline void last_modified(void) /* {{{ */ +static inline void last_modified(void) { const char *path; zend_stat_t sb = {0}; @@ -1294,10 +1252,9 @@ static inline void last_modified(void) /* {{{ */ ADD_HEADER(buf); } } -/* }}} */ #define EXPIRES "Expires: " -CACHE_LIMITER_FUNC(public) /* {{{ */ +CACHE_LIMITER_FUNC(public) { char buf[MAX_STR + 1]; struct timeval tv; @@ -1314,9 +1271,8 @@ CACHE_LIMITER_FUNC(public) /* {{{ */ last_modified(); } -/* }}} */ -CACHE_LIMITER_FUNC(private_no_expire) /* {{{ */ +CACHE_LIMITER_FUNC(private_no_expire) { char buf[MAX_STR + 1]; @@ -1325,16 +1281,14 @@ CACHE_LIMITER_FUNC(private_no_expire) /* {{{ */ last_modified(); } -/* }}} */ -CACHE_LIMITER_FUNC(private) /* {{{ */ +CACHE_LIMITER_FUNC(private) { ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); CACHE_LIMITER(private_no_expire)(); } -/* }}} */ -CACHE_LIMITER_FUNC(nocache) /* {{{ */ +CACHE_LIMITER_FUNC(nocache) { ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); @@ -1344,7 +1298,6 @@ CACHE_LIMITER_FUNC(nocache) /* {{{ */ /* For HTTP/1.0 conforming clients */ ADD_HEADER("Pragma: no-cache"); } -/* }}} */ static const php_session_cache_limiter_t php_session_cache_limiters[] = { CACHE_LIMITER_ENTRY(public) @@ -1354,7 +1307,7 @@ static const php_session_cache_limiter_t php_session_cache_limiters[] = { {0} }; -static int php_session_cache_limiter(void) /* {{{ */ +static int php_session_cache_limiter(void) { const php_session_cache_limiter_t *lim; @@ -1376,7 +1329,6 @@ static int php_session_cache_limiter(void) /* {{{ */ return -1; } -/* }}} */ /* ********************* * Cookie Management * @@ -1425,7 +1377,7 @@ static void php_session_remove_cookie(void) { efree(session_cookie); } -static zend_result php_session_send_cookie(void) /* {{{ */ +static zend_result php_session_send_cookie(void) { smart_str ncookie = {0}; zend_string *date_fmt = NULL; @@ -1499,9 +1451,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */ return SUCCESS; } -/* }}} */ -PHPAPI const ps_module *_php_find_ps_module(const char *name) /* {{{ */ +PHPAPI const ps_module *_php_find_ps_module(const char *name) { const ps_module *ret = NULL; const ps_module **mod; @@ -1515,9 +1466,8 @@ PHPAPI const ps_module *_php_find_ps_module(const char *name) /* {{{ */ } return ret; } -/* }}} */ -PHPAPI const ps_serializer *_php_find_ps_serializer(const char *name) /* {{{ */ +PHPAPI const ps_serializer *_php_find_ps_serializer(const char *name) { const ps_serializer *ret = NULL; const ps_serializer *mod; @@ -1530,7 +1480,6 @@ PHPAPI const ps_serializer *_php_find_ps_serializer(const char *name) /* {{{ */ } return ret; } -/* }}} */ static void ppid2sid(zval *ppid) { ZVAL_DEREF(ppid); @@ -1544,7 +1493,7 @@ static void ppid2sid(zval *ppid) { } -PHPAPI zend_result php_session_reset_id(void) /* {{{ */ +PHPAPI zend_result php_session_reset_id(void) { int module_number = PS(module_number); zval *sid, *data, *ppid; @@ -1614,10 +1563,9 @@ PHPAPI zend_result php_session_reset_id(void) /* {{{ */ } return SUCCESS; } -/* }}} */ -PHPAPI zend_result php_session_start(void) /* {{{ */ +PHPAPI zend_result php_session_start(void) { zval *ppid; zval *data; @@ -1724,9 +1672,8 @@ PHPAPI zend_result php_session_start(void) /* {{{ */ return SUCCESS; } -/* }}} */ -PHPAPI zend_result php_session_flush(int write) /* {{{ */ +PHPAPI zend_result php_session_flush(int write) { if (PS(session_status) == php_session_active) { php_session_save_current_state(write); @@ -1735,14 +1682,13 @@ PHPAPI zend_result php_session_flush(int write) /* {{{ */ } return FAILURE; } -/* }}} */ PHPAPI php_session_status php_get_session_status(void) { return PS(session_status); } -static zend_result php_session_abort(void) /* {{{ */ +static zend_result php_session_abort(void) { if (PS(session_status) == php_session_active) { if (PS(mod_data) || PS(mod_user_implemented)) { @@ -1753,9 +1699,8 @@ static zend_result php_session_abort(void) /* {{{ */ } return FAILURE; } -/* }}} */ -static zend_result php_session_reset(void) /* {{{ */ +static zend_result php_session_reset(void) { if (PS(session_status) == php_session_active && php_session_initialize() == SUCCESS) { @@ -1763,26 +1708,22 @@ static zend_result php_session_reset(void) /* {{{ */ } return FAILURE; } -/* }}} */ /* This API is not used by any PHP modules including session currently. session_adapt_url() may be used to set Session ID to target url without starting "URL-Rewriter" output handler. */ -PHPAPI void session_adapt_url(http://github.com/const%20char%20*url,%20size_t%20url_len,%20char%20**new_url,%20size_t%20*new_len) /* {{{ */ +PHPAPI void session_adapt_url(http://github.com/const%20char%20*url,%20size_t%20url_len,%20char%20**new_url,%20size_t%20*new_len) { if (APPLY_TRANS_SID && (PS(session_status) == php_session_active)) { *new_url = php_url_scanner_adapt_single_url(http://github.com/url,%20url_len,%20PS(session_name), ZSTR_VAL(PS(id)), new_len, 1); } } -/* }}} */ /* ******************************** * Userspace exported functions * ******************************** */ -/* {{{ session_set_cookie_params(array options) - Set session cookie parameters */ PHP_FUNCTION(session_set_cookie_params) { HashTable *options_ht; @@ -1950,9 +1891,7 @@ PHP_FUNCTION(session_set_cookie_params) if (samesite) zend_string_release(samesite); } } -/* }}} */ -/* {{{ Return the session cookie parameters */ PHP_FUNCTION(session_get_cookie_params) { if (zend_parse_parameters_none() == FAILURE) { @@ -1968,9 +1907,8 @@ PHP_FUNCTION(session_get_cookie_params) add_assoc_bool(return_value, "httponly", PS(cookie_httponly)); add_assoc_string(return_value, "samesite", PS(cookie_samesite)); } -/* }}} */ -/* {{{ Return the current session name. If new name is given, the session name is replaced with new name */ +/* Return the current session name. If new name is given, the session name is replaced with new name */ PHP_FUNCTION(session_name) { zend_string *name = NULL; @@ -1998,9 +1936,8 @@ PHP_FUNCTION(session_name) zend_string_release_ex(ini_name, 0); } } -/* }}} */ -/* {{{ Return the current module name used for accessing session data. If newname is given, the module name is replaced with newname */ +/* Return the current module name used for accessing session data. If newname is given, the module name is replaced with newname */ PHP_FUNCTION(session_module_name) { zend_string *name = NULL; @@ -2048,7 +1985,6 @@ PHP_FUNCTION(session_module_name) zend_string_release_ex(ini_name, 0); } } -/* }}} */ static bool can_session_handler_be_changed(void) { if (PS(session_status) == php_session_active) { @@ -2108,7 +2044,6 @@ static inline void set_user_save_handler_ini(void) { SESSION_SET_USER_HANDLER_PROCEDURAL(struct_name, fci); \ } -/* {{{ Sets user-level functions */ PHP_FUNCTION(session_set_save_handler) { /* OOP Version */ @@ -2277,9 +2212,8 @@ PHP_FUNCTION(session_set_save_handler) RETURN_TRUE; } -/* }}} */ -/* {{{ Return the current save path passed to module_name. If newname is given, the save path is replaced with newname */ +/* Return the current save path passed to module_name. If newname is given, the save path is replaced with newname */ PHP_FUNCTION(session_save_path) { zend_string *name = NULL; @@ -2307,9 +2241,8 @@ PHP_FUNCTION(session_save_path) zend_string_release_ex(ini_name, 0); } } -/* }}} */ -/* {{{ Return the current session id. If newid is given, the session id is replaced with newid */ +/* Return the current session id. If newid is given, the session id is replaced with newid */ PHP_FUNCTION(session_id) { zend_string *name = NULL; @@ -2348,9 +2281,8 @@ PHP_FUNCTION(session_id) PS(id) = zend_string_copy(name); } } -/* }}} */ -/* {{{ Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ +/* Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ PHP_FUNCTION(session_regenerate_id) { bool del_ses = 0; @@ -2463,9 +2395,8 @@ PHP_FUNCTION(session_regenerate_id) RETURN_TRUE; } -/* }}} */ -/* {{{ Generate new session ID. Intended for user save handlers. */ +/* Generate new session ID. Intended for user save handlers. */ PHP_FUNCTION(session_create_id) { zend_string *prefix = NULL, *new_id; @@ -2519,9 +2450,8 @@ PHP_FUNCTION(session_create_id) } RETVAL_STR(smart_str_extract(&id)); } -/* }}} */ -/* {{{ Return the current cache limiter. If new_cache_limited is given, the current cache_limiter is replaced with new_cache_limiter */ +/* Return the current cache limiter. If new_cache_limited is given, the current cache_limiter is replaced with new_cache_limiter */ PHP_FUNCTION(session_cache_limiter) { zend_string *limiter = NULL; @@ -2549,9 +2479,8 @@ PHP_FUNCTION(session_cache_limiter) zend_string_release_ex(ini_name, 0); } } -/* }}} */ -/* {{{ Return the current cache expire. If new_cache_expire is given, the current cache_expire is replaced with new_cache_expire */ +/* Return the current cache expire. If new_cache_expire is given, the current cache_expire is replaced with new_cache_expire */ PHP_FUNCTION(session_cache_expire) { zend_long expires; @@ -2581,9 +2510,8 @@ PHP_FUNCTION(session_cache_expire) zend_string_release_ex(ini_value, 0); } } -/* }}} */ -/* {{{ Serializes the current setup and returns the serialized representation */ +/* Serializes the current setup and returns the serialized representation */ PHP_FUNCTION(session_encode) { zend_string *enc; @@ -2599,9 +2527,8 @@ PHP_FUNCTION(session_encode) RETURN_STR(enc); } -/* }}} */ -/* {{{ Deserializes data and reinitializes the variables */ +/* Deserializes data and reinitializes the variables */ PHP_FUNCTION(session_decode) { zend_string *str = NULL; @@ -2620,7 +2547,6 @@ PHP_FUNCTION(session_decode) } RETURN_TRUE; } -/* }}} */ static zend_result php_session_start_set_ini(zend_string *varname, zend_string *new_value) { zend_result ret; @@ -2634,7 +2560,6 @@ static zend_result php_session_start_set_ini(zend_string *varname, zend_string * return ret; } -/* {{{ Begin session */ PHP_FUNCTION(session_start) { zval *options = NULL; @@ -2722,9 +2647,7 @@ PHP_FUNCTION(session_start) RETURN_TRUE; } -/* }}} */ -/* {{{ Destroy the current session and all data associated with it */ PHP_FUNCTION(session_destroy) { if (zend_parse_parameters_none() == FAILURE) { @@ -2733,9 +2656,7 @@ PHP_FUNCTION(session_destroy) RETURN_BOOL(php_session_destroy() == SUCCESS); } -/* }}} */ -/* {{{ Unset all registered variables */ PHP_FUNCTION(session_unset) { if (zend_parse_parameters_none() == FAILURE) { @@ -2755,9 +2676,7 @@ PHP_FUNCTION(session_unset) } RETURN_TRUE; } -/* }}} */ -/* {{{ Perform GC and return number of deleted sessions */ PHP_FUNCTION(session_gc) { zend_long num; @@ -2778,10 +2697,8 @@ PHP_FUNCTION(session_gc) RETURN_LONG(num); } -/* }}} */ -/* {{{ Write session data and end session */ PHP_FUNCTION(session_write_close) { if (zend_parse_parameters_none() == FAILURE) { @@ -2794,9 +2711,8 @@ PHP_FUNCTION(session_write_close) php_session_flush(1); RETURN_TRUE; } -/* }}} */ -/* {{{ Abort session and end session. Session data will not be written */ +/* Abort session and end session. Session data will not be written */ PHP_FUNCTION(session_abort) { if (zend_parse_parameters_none() == FAILURE) { @@ -2809,9 +2725,8 @@ PHP_FUNCTION(session_abort) php_session_abort(); RETURN_TRUE; } -/* }}} */ -/* {{{ Reset session data from saved session data */ +/* Reset session data from saved session data */ PHP_FUNCTION(session_reset) { if (zend_parse_parameters_none() == FAILURE) { @@ -2824,9 +2739,7 @@ PHP_FUNCTION(session_reset) php_session_reset(); RETURN_TRUE; } -/* }}} */ -/* {{{ Returns the current session status */ PHP_FUNCTION(session_status) { if (zend_parse_parameters_none() == FAILURE) { @@ -2835,9 +2748,8 @@ PHP_FUNCTION(session_status) RETURN_LONG(PS(session_status)); } -/* }}} */ -/* {{{ Registers session_write_close() as a shutdown function */ +/* Registers session_write_close() as a shutdown function */ PHP_FUNCTION(session_register_shutdown) { php_shutdown_function_entry shutdown_function_entry = { @@ -2869,13 +2781,12 @@ PHP_FUNCTION(session_register_shutdown) php_error_docref(NULL, E_WARNING, "Session shutdown function cannot be registered"); } } -/* }}} */ /* ******************************** * Module Setup and Destruction * ******************************** */ -static zend_result php_rinit_session(bool auto_start) /* {{{ */ +static zend_result php_rinit_session(bool auto_start) { php_rinit_session_globals(); @@ -2909,13 +2820,12 @@ static zend_result php_rinit_session(bool auto_start) /* {{{ */ } return SUCCESS; -} /* }}} */ +} -static PHP_RINIT_FUNCTION(session) /* {{{ */ +static PHP_RINIT_FUNCTION(session) { return php_rinit_session(PS(auto_start)); } -/* }}} */ #define SESSION_FREE_USER_HANDLER(struct_name) \ if (!Z_ISUNDEF(PS(mod_user_names).struct_name)) { \ @@ -2924,7 +2834,7 @@ static PHP_RINIT_FUNCTION(session) /* {{{ */ } -static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ +static PHP_RSHUTDOWN_FUNCTION(session) { if (PS(session_status) == php_session_active) { zend_try { @@ -2947,9 +2857,8 @@ static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_GINIT_FUNCTION(ps) /* {{{ */ +static PHP_GINIT_FUNCTION(ps) { #if defined(COMPILE_DL_SESSION) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); @@ -2995,9 +2904,8 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */ } php_random_pcgoneseq128xslrr64_seed128(ps_globals->random.state, seed); } -/* }}} */ -static PHP_MINIT_FUNCTION(session) /* {{{ */ +static PHP_MINIT_FUNCTION(session) { zend_register_auto_global(zend_string_init_interned("_SESSION", sizeof("_SESSION") - 1, 1), 0, NULL); @@ -3027,9 +2935,8 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_MSHUTDOWN_FUNCTION(session) /* {{{ */ +static PHP_MSHUTDOWN_FUNCTION(session) { UNREGISTER_INI_ENTRIES(); @@ -3048,9 +2955,8 @@ static PHP_MSHUTDOWN_FUNCTION(session) /* {{{ */ return SUCCESS; } -/* }}} */ -static PHP_MINFO_FUNCTION(session) /* {{{ */ +static PHP_MINFO_FUNCTION(session) { const ps_module **mod; ps_serializer *ser; @@ -3097,19 +3003,17 @@ static PHP_MINFO_FUNCTION(session) /* {{{ */ DISPLAY_INI_ENTRIES(); } -/* }}} */ -static const zend_module_dep session_deps[] = { /* {{{ */ +static const zend_module_dep session_deps[] = { ZEND_MOD_OPTIONAL("spl") ZEND_MOD_END }; -/* }}} */ /* ************************ * Upload hook handling * ************************ */ -static bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progress *progress) /* {{{ */ +static bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progress *progress) { zval *ppid; @@ -3125,9 +3029,9 @@ static bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progres } return 0; -} /* }}} */ +} -static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *progress) /* {{{ */ +static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *progress) { if (PS(use_cookies)) { @@ -3142,9 +3046,9 @@ static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *pro } sapi_module.treat_data(PARSE_GET, NULL, NULL); early_find_sid_in(&progress->sid, TRACK_VARS_GET, progress); -} /* }}} */ +} -static bool php_check_cancel_upload(php_session_rfc1867_progress *progress) /* {{{ */ +static bool php_check_cancel_upload(php_session_rfc1867_progress *progress) { zval *progress_ary, *cancel_upload; @@ -3158,9 +3062,9 @@ static bool php_check_cancel_upload(php_session_rfc1867_progress *progress) /* { return 0; } return Z_TYPE_P(cancel_upload) == IS_TRUE; -} /* }}} */ +} -static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, int force_update) /* {{{ */ +static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, int force_update) { if (!force_update) { if (Z_LVAL_P(progress->post_bytes_processed) < progress->next_update) { @@ -3192,9 +3096,9 @@ static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, i zend_hash_update(Z_ARRVAL_P(sess_var), progress->key.s, &progress->data); } php_session_flush(1); -} /* }}} */ +} -static void php_session_rfc1867_cleanup(php_session_rfc1867_progress *progress) /* {{{ */ +static void php_session_rfc1867_cleanup(php_session_rfc1867_progress *progress) { php_session_initialize(); PS(session_status) = php_session_active; @@ -3204,9 +3108,9 @@ static void php_session_rfc1867_cleanup(php_session_rfc1867_progress *progress) zend_hash_del(Z_ARRVAL_P(sess_var), progress->key.s); } php_session_flush(1); -} /* }}} */ +} -static zend_result php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra) /* {{{ */ +static zend_result php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra) { php_session_rfc1867_progress *progress; zend_result retval = SUCCESS; @@ -3388,8 +3292,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ return FAILURE; } return retval; - -} /* }}} */ +} zend_module_entry session_module_entry = { STANDARD_MODULE_HEADER_EX, From 2a859abd331ceb2f6db8cdf63f488e756cb42e15 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 23:04:40 +0000 Subject: [PATCH 081/503] Remove test dependency on resource/object IDs --- .../scalar_return_basic.phpt | 26 ++++++++--------- .../scalar_return_basic_64bit.phpt | 26 ++++++++--------- .../type_declarations/scalar_strict.phpt | 24 +++++++-------- .../scalar_strict_64bit.phpt | 26 ++++++++--------- ext/opcache/tests/jit/fetch_obj_001.phpt | 4 +-- .../tests/array/array_map_variation4.phpt | 15 ++++------ .../tests/array/array_reverse_variation4.phpt | 18 ++++-------- .../tests/array/array_unique_variation3.phpt | 13 +++------ ext/standard/tests/filters/bug54350.phpt | 2 +- .../tests/general_functions/bug73973.phpt | 2 +- .../tests/general_functions/floatval.phpt | 16 ++-------- .../floatval_variation1.phpt | 29 ++++--------------- 12 files changed, 79 insertions(+), 122 deletions(-) diff --git a/Zend/tests/type_declarations/scalar_return_basic.phpt b/Zend/tests/type_declarations/scalar_return_basic.phpt index 1fd3d26db6d8a..8f827600328ed 100644 --- a/Zend/tests/type_declarations/scalar_return_basic.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic.phpt @@ -44,7 +44,7 @@ $values = [ [], new StdClass, new StringCapable, - fopen("data:text/plain,foobar", "r") + STDERR, ]; foreach ($functions as $type => $function) { @@ -92,13 +92,13 @@ int(0) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type int, resource returned in %s on line %d Testing 'float' type: @@ -129,13 +129,13 @@ float(0) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type float, resource returned in %s on line %d Testing 'string' type: @@ -166,13 +166,13 @@ string(0) "" *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type string, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type string, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } string(6) "foobar" -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type string, resource returned in %s on line %d Testing 'bool' type: @@ -203,13 +203,13 @@ bool(false) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type bool, resource returned in %s on line %d Done diff --git a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt index da930b98d9b65..0a32dd3f16f23 100644 --- a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt @@ -44,7 +44,7 @@ $values = [ [], new StdClass, new StringCapable, - fopen("data:text/plain,foobar", "r") + STDERR, ]; foreach ($functions as $type => $function) { @@ -92,13 +92,13 @@ int(0) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type int, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type int, resource returned in %s on line %d Testing 'float' type: @@ -129,13 +129,13 @@ float(0) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type float, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type float, resource returned in %s on line %d Testing 'string' type: @@ -166,13 +166,13 @@ string(0) "" *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type string, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type string, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } string(6) "foobar" -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type string, resource returned in %s on line %d Testing 'bool' type: @@ -203,13 +203,13 @@ bool(false) *** Trying array(0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, array returned in %s on line %d -*** Trying object(stdClass)#6 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, stdClass returned in %s on line %d -*** Trying object(StringCapable)#7 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Return value must be of type bool, StringCapable returned in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Return value must be of type bool, resource returned in %s on line %d Done diff --git a/Zend/tests/type_declarations/scalar_strict.phpt b/Zend/tests/type_declarations/scalar_strict.phpt index e89d18b2c86b3..626f322d8701f 100644 --- a/Zend/tests/type_declarations/scalar_strict.phpt +++ b/Zend/tests/type_declarations/scalar_strict.phpt @@ -96,15 +96,15 @@ int(2147483647) } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, resource given, called in %s on line %d Testing 'float' type: @@ -149,15 +149,15 @@ float(NAN) } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, resource given, called in %s on line %d Testing 'string' type: @@ -202,15 +202,15 @@ string(0) "" } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, resource given, called in %s on line %d Testing 'bool' type: @@ -255,15 +255,15 @@ bool(false) } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, resource given, called in %s on line %d Done diff --git a/Zend/tests/type_declarations/scalar_strict_64bit.phpt b/Zend/tests/type_declarations/scalar_strict_64bit.phpt index 6335e2d1acee4..b7f2ce0de4396 100644 --- a/Zend/tests/type_declarations/scalar_strict_64bit.phpt +++ b/Zend/tests/type_declarations/scalar_strict_64bit.phpt @@ -35,7 +35,7 @@ $values = [ [], new StdClass, new StringCapable, - fopen("data:text/plain,foobar", "r") + STDERR, ]; foreach ($functions as $type => $function) { @@ -96,15 +96,15 @@ int(9223372036854775807) } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($i) must be of type int, resource given, called in %s on line %d Testing 'float' type: @@ -149,15 +149,15 @@ float(NAN) } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($f) must be of type float, resource given, called in %s on line %d Testing 'string' type: @@ -202,15 +202,15 @@ string(0) "" } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($s) must be of type string, resource given, called in %s on line %d Testing 'bool' type: @@ -255,15 +255,15 @@ bool(false) } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, array given, called in %s on line %d -*** Trying object(stdClass)#5 (0) { +*** Trying object(stdClass)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, stdClass given, called in %s on line %d -*** Trying object(StringCapable)#6 (0) { +*** Trying object(StringCapable)#%d (0) { } *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, StringCapable given, called in %s on line %d -*** Trying resource(5) of type (stream) +*** Trying resource(%d) of type (stream) *** Caught {closure:%s:%d}(): Argument #1 ($b) must be of type bool, resource given, called in %s on line %d Done diff --git a/ext/opcache/tests/jit/fetch_obj_001.phpt b/ext/opcache/tests/jit/fetch_obj_001.phpt index 0f68c1aae0991..ddc8dfafba648 100644 --- a/ext/opcache/tests/jit/fetch_obj_001.phpt +++ b/ext/opcache/tests/jit/fetch_obj_001.phpt @@ -96,7 +96,7 @@ object(stdClass)#%d (2) { } object(stdClass)#%d (2) { ["a"]=> - &resource(5) of type (stream) + &resource(%d) of type (stream) ["b"]=> array(0) { } @@ -122,7 +122,7 @@ object(stdClass)#%d (2) { } object(stdClass)#%d (2) { ["a"]=> - &resource(6) of type (stream) + &resource(%d) of type (stream) ["b"]=> array(0) { } diff --git a/ext/standard/tests/array/array_map_variation4.phpt b/ext/standard/tests/array/array_map_variation4.phpt index 4d6269b3617db..d75a0bcf26108 100644 --- a/ext/standard/tests/array/array_map_variation4.phpt +++ b/ext/standard/tests/array/array_map_variation4.phpt @@ -17,9 +17,6 @@ function callback($a) $unset_var = 10; unset ($unset_var); -// get a resource variable -$fp = fopen(__FILE__, "r"); - // get a class class classA{ public function __toString(){ @@ -49,11 +46,11 @@ $arrays = array ( array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable - array(@$unset_var => "hello", $fp => 'resource'), + array(@$unset_var => "hello", STDERR => 'resource'), // array with mixed values /*11*/ array('hello' => 1, "fruit" => 2.2, - $fp => 'resource', 133 => "int", + STDERR => 'resource', 133 => "int", @$unset_var => "unset", $heredoc => "heredoc") ); @@ -70,9 +67,9 @@ echo "Done"; --EXPECTF-- *** Testing array_map() : associative array with diff. keys for 'arr1' argument *** -Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line %d -Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line %d -- Iteration 1 -- array(0) { } @@ -131,7 +128,7 @@ array(2) { array(2) { [""]=> string(5) "hello" - [5]=> + [3]=> string(8) "resource" } -- Iteration 9 -- @@ -140,7 +137,7 @@ array(6) { int(1) ["fruit"]=> float(2.2) - [5]=> + [3]=> string(8) "resource" [133]=> string(3) "int" diff --git a/ext/standard/tests/array/array_reverse_variation4.phpt b/ext/standard/tests/array/array_reverse_variation4.phpt index 07454f5a1f261..4967f6e4dacb0 100644 --- a/ext/standard/tests/array/array_reverse_variation4.phpt +++ b/ext/standard/tests/array/array_reverse_variation4.phpt @@ -13,9 +13,6 @@ echo "*** Testing array_reverse() : usage variations ***\n"; $unset_var = 10; unset ($unset_var); -//get a resource variable -$fp = fopen(__FILE__, "r"); - //get a class class classA{ public function __toString(){ @@ -45,10 +42,10 @@ $arrays = array ( array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable - array(@$unset_var => "hello", $fp => 'resource'), + array(@$unset_var => "hello", STDERR => 'resource'), // array with mixed values -/*11*/ array('hello' => 1, "fruit" => 2.2, $fp => 'resource', 133 => "int", @$unset_var => "unset", $heredoc => "heredoc") +/*11*/ array('hello' => 1, "fruit" => 2.2, STDERR => 'resource', 133 => "int", @$unset_var => "unset", $heredoc => "heredoc") ); // loop through the various elements of $arrays to test array_reverse() @@ -66,17 +63,14 @@ foreach($arrays as $array) { $iterator++; }; -// close the file resource used -fclose($fp); - echo "Done"; ?> --EXPECTF-- *** Testing array_reverse() : usage variations *** -Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line %d -Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line %d -- Iteration 1 -- - default argument - array(0) { @@ -259,7 +253,7 @@ array(2) { } - $preserve keys = true - array(2) { - [5]=> + [3]=> string(8) "resource" [""]=> string(5) "hello" @@ -295,7 +289,7 @@ array(6) { string(5) "unset" [133]=> string(3) "int" - [5]=> + [3]=> string(8) "resource" ["fruit"]=> float(2.2) diff --git a/ext/standard/tests/array/array_unique_variation3.phpt b/ext/standard/tests/array/array_unique_variation3.phpt index b412a19a422e5..91b551bb60402 100644 --- a/ext/standard/tests/array/array_unique_variation3.phpt +++ b/ext/standard/tests/array/array_unique_variation3.phpt @@ -13,9 +13,6 @@ echo "*** Testing array_unique() : assoc. array with diff. keys passed to \$inpu $unset_var = 10; unset ($unset_var); -// get a resource variable -$fp = fopen(__FILE__, "r"); - // get a class class classA { @@ -41,7 +38,7 @@ $inputs = array ( array("hello", $heredoc => "string", "string"), // array with object, unset variable and resource variable -/*8*/ array(@$unset_var => "hello", $fp => 'resource', 11, "hello"), +/*8*/ array(@$unset_var => "hello", STDERR => 'resource', 11, "hello"), ); // loop through each sub-array of $inputs to check the behavior of array_unique() @@ -52,14 +49,12 @@ foreach($inputs as $input) { $iterator++; } -fclose($fp); - echo "Done"; ?> --EXPECTF-- *** Testing array_unique() : assoc. array with diff. keys passed to $input argument *** -Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line %d -- Iteration 1 -- array(1) { [0]=> @@ -103,9 +98,9 @@ array(2) { array(3) { [""]=> string(5) "hello" - [5]=> + [3]=> string(8) "resource" - [6]=> + [4]=> int(11) } Done diff --git a/ext/standard/tests/filters/bug54350.phpt b/ext/standard/tests/filters/bug54350.phpt index a017893eed7bb..ae00762890857 100644 --- a/ext/standard/tests/filters/bug54350.phpt +++ b/ext/standard/tests/filters/bug54350.phpt @@ -22,5 +22,5 @@ fwrite($fd, "foo"); ?> --EXPECTF-- -Warning: fclose(): 5 is not a valid stream resource in %s on line %d +Warning: fclose(): %d is not a valid stream resource in %s on line %d fclose(): supplied resource is not a valid stream resource diff --git a/ext/standard/tests/general_functions/bug73973.phpt b/ext/standard/tests/general_functions/bug73973.phpt index 8bb4daaab094d..fccd8b5af9457 100644 --- a/ext/standard/tests/general_functions/bug73973.phpt +++ b/ext/standard/tests/general_functions/bug73973.phpt @@ -6,4 +6,4 @@ define('myerr', fopen('php://stderr', 'w')); debug_zval_dump(myerr); ?> --EXPECTF-- -resource(5) of type (stream) refcount(%d) +resource(%d) of type (stream) refcount(%d) diff --git a/ext/standard/tests/general_functions/floatval.phpt b/ext/standard/tests/general_functions/floatval.phpt index f9aa74e342d56..9ff49bb01084e 100644 --- a/ext/standard/tests/general_functions/floatval.phpt +++ b/ext/standard/tests/general_functions/floatval.phpt @@ -47,18 +47,11 @@ foreach ($valid_floats as $value ) { echo "\n*** Testing floatval() on non floating types ***\n"; -// get a resource type variable -$fp = fopen (__FILE__, "r"); -fclose($fp); -$dfp = opendir ( __DIR__ ); -closedir($dfp); - // other types in an array $not_float_types = array ( -2147483648, // max negative integer value 2147483648, // max positive integer value - $fp, // resource - $dfp, + STDERR, // resource "0.0", // string "1.0", "-1.3e3", @@ -89,7 +82,6 @@ foreach ($not_float_types as $type ) { echo "\nDone\n"; - ?> --EXPECTF-- *** Testing floatval() with valid float values *** @@ -145,8 +137,7 @@ Warning: A non-numeric value encountered in %s on line %d Warning: A non-numeric value encountered in %s on line %d float(-2147483648) float(2147483648) -float(5) -float(6) +float(3) float(0) float(1) float(-1300) @@ -163,8 +154,7 @@ float(0) *** Testing doubleval() on non floating types *** float(-2147483648) float(2147483648) -float(5) -float(6) +float(3) float(0) float(1) float(-1300) diff --git a/ext/standard/tests/general_functions/floatval_variation1.phpt b/ext/standard/tests/general_functions/floatval_variation1.phpt index 856e4e31ebb0d..032d089b01c49 100644 --- a/ext/standard/tests/general_functions/floatval_variation1.phpt +++ b/ext/standard/tests/general_functions/floatval_variation1.phpt @@ -2,18 +2,12 @@ Testing floatval() and its alias doubleval() functions : usage variations - different data types as $y arg --FILE-- -2147483648, // max negative integer value "2147483647" => 2147483648, // max positive integer value - "file resoruce" => $fp, - "directory resource" => $dfp, + "stream resource" => STDERR, "\"0.0\"" => "0.0", // string "\"1.0\"" => "1.0", "\"-1.3e3\"" => "-1.3e3", @@ -24,7 +18,6 @@ $not_float_types = array ( "\"10.0 dollar\" + 1.0" => "10.0 dollar" + 1.0, "\"\"" => "", "true" => true, - "NULL" => NULL, "null" => null, ); /* loop through the $not_float_types to see working of @@ -57,11 +50,8 @@ float(-2147483648) -- Iteration : 2147483647 -- float(2147483648) --- Iteration : file resoruce -- -float(5) - --- Iteration : directory resource -- -float(6) +-- Iteration : stream resource -- +float(3) -- Iteration : "0.0" -- float(0) @@ -93,9 +83,6 @@ float(0) -- Iteration : true -- float(1) --- Iteration : NULL -- -float(0) - -- Iteration : null -- float(0) @@ -107,11 +94,8 @@ float(-2147483648) -- Iteration : 2147483647 -- float(2147483648) --- Iteration : file resoruce -- -float(5) - --- Iteration : directory resource -- -float(6) +-- Iteration : stream resource -- +float(3) -- Iteration : "0.0" -- float(0) @@ -143,8 +127,5 @@ float(0) -- Iteration : true -- float(1) --- Iteration : NULL -- -float(0) - -- Iteration : null -- float(0) From 83090b47054d49ef8834d4d3b426c982ca478a04 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 4 Mar 2025 02:20:34 +0000 Subject: [PATCH 082/503] Split print_r tests So that these aren't huge mega tests --- .../tests/general_functions/print_r.phpt | 1696 ---------------- .../general_functions/print_r_64bit.phpt | 1700 ----------------- .../print_r_array_circular.phpt | 22 + .../general_functions/print_r_arrays.phpt | 166 ++ .../print_r_arrays_whitespace_sensitive.phpt | 50 + .../general_functions/print_r_bools.phpt | 28 + .../general_functions/print_r_floats.phpt | 183 ++ .../tests/general_functions/print_r_ints.phpt | 131 ++ .../general_functions/print_r_ints_64bit.phpt | 45 + .../tests/general_functions/print_r_null.phpt | 18 + .../general_functions/print_r_object.phpt | 228 +++ .../print_r_object_circular.phpt | 26 + .../general_functions/print_r_resources.phpt | 23 + .../general_functions/print_r_strings.phpt | 61 + .../print_r_strings_nul_bytes.phpt | Bin 0 -> 916 bytes 15 files changed, 981 insertions(+), 3396 deletions(-) delete mode 100644 ext/standard/tests/general_functions/print_r.phpt delete mode 100644 ext/standard/tests/general_functions/print_r_64bit.phpt create mode 100644 ext/standard/tests/general_functions/print_r_array_circular.phpt create mode 100644 ext/standard/tests/general_functions/print_r_arrays.phpt create mode 100644 ext/standard/tests/general_functions/print_r_arrays_whitespace_sensitive.phpt create mode 100644 ext/standard/tests/general_functions/print_r_bools.phpt create mode 100644 ext/standard/tests/general_functions/print_r_floats.phpt create mode 100644 ext/standard/tests/general_functions/print_r_ints.phpt create mode 100644 ext/standard/tests/general_functions/print_r_ints_64bit.phpt create mode 100644 ext/standard/tests/general_functions/print_r_null.phpt create mode 100644 ext/standard/tests/general_functions/print_r_object.phpt create mode 100644 ext/standard/tests/general_functions/print_r_object_circular.phpt create mode 100644 ext/standard/tests/general_functions/print_r_resources.phpt create mode 100644 ext/standard/tests/general_functions/print_r_strings.phpt create mode 100644 ext/standard/tests/general_functions/print_r_strings_nul_bytes.phpt diff --git a/ext/standard/tests/general_functions/print_r.phpt b/ext/standard/tests/general_functions/print_r.phpt deleted file mode 100644 index 0ea60658aed7a..0000000000000 --- a/ext/standard/tests/general_functions/print_r.phpt +++ /dev/null @@ -1,1696 +0,0 @@ ---TEST-- -Test print_r() function ---INI-- -precision=14 ---FILE-- - 'One'), - array("test" => "is_array"), - array(0), - array(-1), - array(10.5, 5.6), - array("string", "test"), - array('string', 'test'), -); -/* calling check_printr() to display contents of $arrays */ -check_printr($arrays); - -echo "\n*** Testing print_r() on object variables ***\n"; -#[AllowDynamicProperties] -class object_class -{ - var $value; - public $public_var1 = 10; - private $private_var1 = 20; - private $private_var2; - protected $protected_var1 = "string_1"; - protected $protected_var2; - - function __construct() { - $this->value = 50; - $this->public_var2 = 11; - $this->private_var2 = 21; - $this->protected_var2 = "string_2"; - } - - public function foo1() { - echo "foo1() is called\n"; - } - protected function foo2() { - echo "foo2() is called\n"; - } - private function foo3() { - echo "foo3() is called\n"; - } -} -/* class with no member */ -class no_member_class { - // no members -} - -/* class with member as object of other class */ -#[AllowDynamicProperties] -class contains_object_class -{ - var $p = 30; - var $class_object1; - public $class_object2; - private $class_object3; - protected $class_object4; - var $no_member_class_object; - - public function func() { - echo "func() is called \n"; - } - - function __construct() { - $this->class_object1 = new object_class(); - $this->class_object2 = new object_class(); - $this->class_object3 = $this->class_object1; - $this->class_object4 = $this->class_object2; - $this->no_member_class_object = new no_member_class(); - $this->class_object5 = $this; //recursive reference - } -} - -/* objects of different classes */ -$obj = new contains_object_class; -$temp_class_obj = new object_class(); - -/* object which is unset */ -$unset_obj = new object_class(); -unset($unset_obj); - -$objects = array ( - new object_class, - new no_member_class, - new contains_object_class, - $obj, - $obj->class_object1, - $obj->class_object2, - $obj->no_member_class_object, - $temp_class_obj, - @$unset_obj -); -/* calling check_printr() to display contents of the objects using print_r() */ -check_printr($objects); - -echo "\n** Testing print_r() on objects having circular reference **\n"; -$recursion_obj1 = new object_class(); -$recursion_obj2 = new object_class(); -$recursion_obj1->obj = &$recursion_obj2; //circular reference -$recursion_obj2->obj = &$recursion_obj1; //circular reference -print_r($recursion_obj2); - -echo "\n*** Testing print_r() on resources ***\n"; -/* file type resource */ -$file_handle = fopen(__FILE__, "r"); - -/* directory type resource */ -$dir_handle = opendir( __DIR__ ); - -$resources = array ( - $file_handle, - $dir_handle -); -/* calling check_printr() to display the resource content type - using print_r() */ -check_printr($resources); - -echo "\n*** Testing print_r() on different combinations of scalar - and non-scalar variables ***\n"; -/* a variable which is unset */ -$unset_var = 10.5; -unset($unset_var); - -/* unset file type resource */ -unset($file_handle); - -$variations = array ( - array( 123, -1.2345, "a" ), - array( "d", array(1, 3, 5), true, null), - array( new no_member_class, array(), false, 0 ), - array( -0.00, "Where am I?", array(7,8,9), TRUE, 'A', 987654321 ), - array( @$unset_var, 2.E+10, 100-20.9, 000004.599998 ), //unusual data - array( "array(1,2,3,4)1.0000002TRUE", @$file_handle, 111333.00+45e5, '/00\7') -); -/* calling check_printr() to display combinations of scalar and - non-scalar variables using print_r() */ -check_printr($variations); - -echo "\n*** Testing print_r() on miscellaneous input arguments ***\n"; -$misc_values = array ( - @$unset_var, - NULL, // NULL argument - @$undef_variable, //undefined variable - null -); -/* calling check_printr() to display miscellaneous data using print_r() */ -check_printr($misc_values); - -/* closing resource handle used */ -closedir($dir_handle); - -echo "Done\n"; -?> ---EXPECTF-- -*** Testing print_r() on integer variables *** - --- Iteration 1 -- -0 -0 -0 --- Iteration 2 -- -83 -83 -83 --- Iteration 3 -- -123000000 -123000000 -123000000 --- Iteration 4 -- --83 --83 --83 --- Iteration 5 -- --12300000 --12300000 --12300000 --- Iteration 6 -- -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - --- Iteration 7 -- -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - --- Iteration 8 -- -2147483647 -2147483647 -2147483647 --- Iteration 9 -- -2147483648 -2147483648 -2147483648 --- Iteration 10 -- --2147483648 --2147483648 --2147483648 --- Iteration 11 -- --2147483647 --2147483647 --2147483647 --- Iteration 12 -- -2147483647 -2147483647 -2147483647 --- Iteration 13 -- --2147483648 --2147483648 --2147483648 --- Iteration 14 -- -2147483647 -2147483647 -2147483647 --- Iteration 15 -- --2147483648 --2147483648 --2147483648 -*** Testing print_r() on float variables *** - --- Iteration 1 -- --0 --0 --0 --- Iteration 2 -- -0 -0 -0 --- Iteration 3 -- -1.234 -1.234 -1.234 --- Iteration 4 -- --1.234 --1.234 --1.234 --- Iteration 5 -- --2 --2 --2 --- Iteration 6 -- -2 -2 -2 --- Iteration 7 -- --0.5 --0.5 --0.5 --- Iteration 8 -- -0.567 -0.567 -0.567 --- Iteration 9 -- --0.00067 --0.00067 --0.00067 --- Iteration 10 -- --670 --670 --670 --- Iteration 11 -- -670 -670 -670 --- Iteration 12 -- -670 -670 -670 --- Iteration 13 -- --0.00410003 --0.00410003 --0.00410003 --- Iteration 14 -- --4100.03 --4100.03 --4100.03 --- Iteration 15 -- -0.004100003 -0.004100003 -0.004100003 --- Iteration 16 -- -4100.003 -4100.003 -4100.003 --- Iteration 17 -- -100000 -100000 -100000 --- Iteration 18 -- --100000 --100000 --100000 --- Iteration 19 -- -1.0E-5 -1.0E-5 -1.0E-5 --- Iteration 20 -- --1.0E-5 --1.0E-5 --1.0E-5 --- Iteration 21 -- -100000 -100000 -100000 --- Iteration 22 -- --100000 --100000 --100000 --- Iteration 23 -- -100000 -100000 -100000 --- Iteration 24 -- --100000 --100000 --100000 --- Iteration 25 -- -100000 -100000 -100000 --- Iteration 26 -- --100000 --100000 --100000 --- Iteration 27 -- -1.0E-5 -1.0E-5 -1.0E-5 --- Iteration 28 -- --1.0E-5 --1.0E-5 --1.0E-5 --- Iteration 29 -- --2147483649 --2147483649 --2147483649 --- Iteration 30 -- -2147483649 -2147483649 -2147483649 --- Iteration 31 -- -2147483649 -2147483649 -2147483649 --- Iteration 32 -- --2147483649 --2147483649 --2147483649 -*** Testing print_r() on string variables *** - --- Iteration 1 -- - - - --- Iteration 2 -- - - - --- Iteration 3 -- - - - --- Iteration 4 -- - - - --- Iteration 5 -- -0 -0 -0 --- Iteration 6 -- -%0 -%0 -%0 --- Iteration 7 -- -\0 -\0 -\0 --- Iteration 8 -- - - - --- Iteration 9 -- -\t -\t -\t --- Iteration 10 -- -PHP -PHP -PHP --- Iteration 11 -- -PHP -PHP -PHP --- Iteration 12 -- -abcd%0n1234%005678%000efgh\xijkl -abcd%0n1234%005678%000efgh\xijkl -abcd%0n1234%005678%000efgh\xijkl --- Iteration 13 -- -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz --- Iteration 14 -- -1234 -5678 - 9100"abcda -1234 -5678 - 9100"abcda -1234 -5678 - 9100"abcda -*** Testing print_r() on boolean variables *** - --- Iteration 1 -- -1 -1 -1 --- Iteration 2 -- - - - --- Iteration 3 -- -1 -1 -1 --- Iteration 4 -- - - -bool(true) - -bool(true) - -*** Testing print_r() on array variables *** - --- Iteration 1 -- -Array -( -) - -Array -( -) - -Array -( -) - --- Iteration 2 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 3 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 4 -- -Array -( - [0] => 1 -) - -Array -( - [0] => 1 -) - -Array -( - [0] => 1 -) - --- Iteration 5 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 6 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 7 -- -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - --- Iteration 8 -- -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - --- Iteration 9 -- -Array -( - [1] => One -) - -Array -( - [1] => One -) - -Array -( - [1] => One -) - --- Iteration 10 -- -Array -( - [test] => is_array -) - -Array -( - [test] => is_array -) - -Array -( - [test] => is_array -) - --- Iteration 11 -- -Array -( - [0] => 0 -) - -Array -( - [0] => 0 -) - -Array -( - [0] => 0 -) - --- Iteration 12 -- -Array -( - [0] => -1 -) - -Array -( - [0] => -1 -) - -Array -( - [0] => -1 -) - --- Iteration 13 -- -Array -( - [0] => 10.5 - [1] => 5.6 -) - -Array -( - [0] => 10.5 - [1] => 5.6 -) - -Array -( - [0] => 10.5 - [1] => 5.6 -) - --- Iteration 14 -- -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - --- Iteration 15 -- -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -*** Testing print_r() on object variables *** - --- Iteration 1 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 2 -- -no_member_class Object -( -) - -no_member_class Object -( -) - -no_member_class Object -( -) - --- Iteration 3 -- -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - --- Iteration 4 -- -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - --- Iteration 5 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 6 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 7 -- -no_member_class Object -( -) - -no_member_class Object -( -) - -no_member_class Object -( -) - --- Iteration 8 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 9 -- - - - -** Testing print_r() on objects having circular reference ** -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - [obj] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - [obj] => object_class Object - *RECURSION* - ) - -) - -*** Testing print_r() on resources *** - --- Iteration 1 -- -Resource id #5 -Resource id #5 -Resource id #5 --- Iteration 2 -- -Resource id #6 -Resource id #6 -Resource id #6 -*** Testing print_r() on different combinations of scalar - and non-scalar variables *** - --- Iteration 1 -- -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - --- Iteration 2 -- -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - --- Iteration 3 -- -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - --- Iteration 4 -- -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - --- Iteration 5 -- -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - --- Iteration 6 -- -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -*** Testing print_r() on miscellaneous input arguments *** - --- Iteration 1 -- - - - --- Iteration 2 -- - - - --- Iteration 3 -- - - - --- Iteration 4 -- - - -Done diff --git a/ext/standard/tests/general_functions/print_r_64bit.phpt b/ext/standard/tests/general_functions/print_r_64bit.phpt deleted file mode 100644 index 6026b959d7c4c..0000000000000 --- a/ext/standard/tests/general_functions/print_r_64bit.phpt +++ /dev/null @@ -1,1700 +0,0 @@ ---TEST-- -Test print_r() function ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- - 'One'), - array("test" => "is_array"), - array(0), - array(-1), - array(10.5, 5.6), - array("string", "test"), - array('string', 'test'), -); -/* calling check_printr() to display contents of $arrays */ -check_printr($arrays); - -echo "\n*** Testing print_r() on object variables ***\n"; -#[AllowDynamicProperties] -class object_class -{ - var $value; - public $public_var1 = 10; - private $private_var1 = 20; - private $private_var2; - protected $protected_var1 = "string_1"; - protected $protected_var2; - - function __construct ( ) { - $this->value = 50; - $this->public_var2 = 11; - $this->private_var2 = 21; - $this->protected_var2 = "string_2"; - } - - public function foo1() { - echo "foo1() is called\n"; - } - protected function foo2() { - echo "foo2() is called\n"; - } - private function foo3() { - echo "foo3() is called\n"; - } -} -/* class with no member */ -class no_member_class { - // no members -} - -/* class with member as object of other class */ -#[AllowDynamicProperties] -class contains_object_class -{ - var $p = 30; - var $class_object1; - public $class_object2; - private $class_object3; - protected $class_object4; - var $no_member_class_object; - - public function func() { - echo "func() is called \n"; - } - - function __construct () { - $this->class_object1 = new object_class(); - $this->class_object2 = new object_class(); - $this->class_object3 = $this->class_object1; - $this->class_object4 = $this->class_object2; - $this->no_member_class_object = new no_member_class(); - $this->class_object5 = $this; //recursive reference - } -} - -/* objects of different classes */ -$obj = new contains_object_class; -$temp_class_obj = new object_class(); - -/* object which is unset */ -$unset_obj = new object_class(); -unset($unset_obj); - -$objects = array ( - new object_class, - new no_member_class, - new contains_object_class, - $obj, - $obj->class_object1, - $obj->class_object2, - $obj->no_member_class_object, - $temp_class_obj, - @$unset_obj -); -/* calling check_printr() to display contents of the objects using print_r() */ -check_printr($objects); - -echo "\n** Testing print_r() on objects having circular reference **\n"; -$recursion_obj1 = new object_class(); -$recursion_obj2 = new object_class(); -$recursion_obj1->obj = &$recursion_obj2; //circular reference -$recursion_obj2->obj = &$recursion_obj1; //circular reference -print_r($recursion_obj2); - -echo "\n*** Testing print_r() on resources ***\n"; -/* file type resource */ -$file_handle = fopen(__FILE__, "r"); - -/* directory type resource */ -$dir_handle = opendir( __DIR__ ); - -$resources = array ( - $file_handle, - $dir_handle -); -/* calling check_printr() to display the resource content type - using print_r() */ -check_printr($resources); - -echo "\n*** Testing print_r() on different combinations of scalar - and non-scalar variables ***\n"; -/* a variable which is unset */ -$unset_var = 10.5; -unset($unset_var); - -/* unset file type resource */ -unset($file_handle); - -$variations = array ( - array( 123, -1.2345, "a" ), - array( "d", array(1, 3, 5), true, null), - array( new no_member_class, array(), false, 0 ), - array( -0.00, "Where am I?", array(7,8,9), TRUE, 'A', 987654321 ), - array( @$unset_var, 2.E+10, 100-20.9, 000004.599998 ), //unusual data - array( "array(1,2,3,4)1.0000002TRUE", @$file_handle, 111333.00+45e5, '/00\7') -); -/* calling check_printr() to display combinations of scalar and - non-scalar variables using print_r() */ -check_printr($variations); - -echo "\n*** Testing print_r() on miscellaneous input arguments ***\n"; -$misc_values = array ( - @$unset_var, - NULL, // NULL argument - @$undef_variable, //undefined variable - null -); -/* calling check_printr() to display miscellaneous data using print_r() */ -check_printr($misc_values); - -/* closing resource handle used */ -closedir($dir_handle); - -echo "Done\n"; -?> ---EXPECTF-- -*** Testing print_r() on integer variables *** - --- Iteration 1 -- -0 -0 -0 --- Iteration 2 -- -83 -83 -83 --- Iteration 3 -- -123000000 -123000000 -123000000 --- Iteration 4 -- --83 --83 --83 --- Iteration 5 -- --12300000 --12300000 --12300000 --- Iteration 6 -- -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - -Array -( - [0] => 1 - [1] => 2 - [2] => 3 - [3] => 4 - [4] => 5 - [5] => 6 - [6] => 7 - [7] => 8 - [8] => 9 - [9] => 10 -) - --- Iteration 7 -- -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - -Array -( - [0] => -1 - [1] => -2 - [2] => -3 - [3] => -4 - [4] => -5 - [5] => -6 - [6] => -7 - [7] => -8 - [8] => -9 - [9] => -10 -) - --- Iteration 8 -- -2147483647 -2147483647 -2147483647 --- Iteration 9 -- -2147483648 -2147483648 -2147483648 --- Iteration 10 -- --2147483648 --2147483648 --2147483648 --- Iteration 11 -- --2147483647 --2147483647 --2147483647 --- Iteration 12 -- -2147483647 -2147483647 -2147483647 --- Iteration 13 -- --2147483648 --2147483648 --2147483648 --- Iteration 14 -- -2147483647 -2147483647 -2147483647 --- Iteration 15 -- --2147483648 --2147483648 --2147483648 -*** Testing print_r() on float variables *** - --- Iteration 1 -- --0 --0 --0 --- Iteration 2 -- -0 -0 -0 --- Iteration 3 -- -1.234 -1.234 -1.234 --- Iteration 4 -- --1.234 --1.234 --1.234 --- Iteration 5 -- --2 --2 --2 --- Iteration 6 -- -2 -2 -2 --- Iteration 7 -- --0.5 --0.5 --0.5 --- Iteration 8 -- -0.567 -0.567 -0.567 --- Iteration 9 -- --0.00067 --0.00067 --0.00067 --- Iteration 10 -- --670 --670 --670 --- Iteration 11 -- -670 -670 -670 --- Iteration 12 -- -670 -670 -670 --- Iteration 13 -- --0.00410003 --0.00410003 --0.00410003 --- Iteration 14 -- --4100.03 --4100.03 --4100.03 --- Iteration 15 -- -0.004100003 -0.004100003 -0.004100003 --- Iteration 16 -- -4100.003 -4100.003 -4100.003 --- Iteration 17 -- -100000 -100000 -100000 --- Iteration 18 -- --100000 --100000 --100000 --- Iteration 19 -- -1.0E-5 -1.0E-5 -1.0E-5 --- Iteration 20 -- --1.0E-5 --1.0E-5 --1.0E-5 --- Iteration 21 -- -100000 -100000 -100000 --- Iteration 22 -- --100000 --100000 --100000 --- Iteration 23 -- -100000 -100000 -100000 --- Iteration 24 -- --100000 --100000 --100000 --- Iteration 25 -- -100000 -100000 -100000 --- Iteration 26 -- --100000 --100000 --100000 --- Iteration 27 -- -1.0E-5 -1.0E-5 -1.0E-5 --- Iteration 28 -- --1.0E-5 --1.0E-5 --1.0E-5 --- Iteration 29 -- --2147483649 --2147483649 --2147483649 --- Iteration 30 -- -2147483649 -2147483649 -2147483649 --- Iteration 31 -- -2147483649 -2147483649 -2147483649 --- Iteration 32 -- --2147483649 --2147483649 --2147483649 -*** Testing print_r() on string variables *** - --- Iteration 1 -- - - - --- Iteration 2 -- - - - --- Iteration 3 -- - - - --- Iteration 4 -- - - - --- Iteration 5 -- -0 -0 -0 --- Iteration 6 -- -%0 -%0 -%0 --- Iteration 7 -- -\0 -\0 -\0 --- Iteration 8 -- - - - --- Iteration 9 -- -\t -\t -\t --- Iteration 10 -- -PHP -PHP -PHP --- Iteration 11 -- -PHP -PHP -PHP --- Iteration 12 -- -abcd%0n1234%005678%000efgh\xijkl -abcd%0n1234%005678%000efgh\xijkl -abcd%0n1234%005678%000efgh\xijkl --- Iteration 13 -- -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz -abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz --- Iteration 14 -- -1234 -5678 - 9100"abcda -1234 -5678 - 9100"abcda -1234 -5678 - 9100"abcda -*** Testing print_r() on boolean variables *** - --- Iteration 1 -- -1 -1 -1 --- Iteration 2 -- - - - --- Iteration 3 -- -1 -1 -1 --- Iteration 4 -- - - -bool(true) - -bool(true) - -*** Testing print_r() on array variables *** - --- Iteration 1 -- -Array -( -) - -Array -( -) - -Array -( -) - --- Iteration 2 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 3 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 4 -- -Array -( - [0] => 1 -) - -Array -( - [0] => 1 -) - -Array -( - [0] => 1 -) - --- Iteration 5 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 6 -- -Array -( - [0] => -) - -Array -( - [0] => -) - -Array -( - [0] => -) - --- Iteration 7 -- -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - -Array -( - [0] => Array - ( - ) - - [1] => Array - ( - ) - -) - --- Iteration 8 -- -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - -Array -( - [0] => Array - ( - [0] => 1 - [1] => 2 - ) - - [1] => Array - ( - [0] => a - [1] => b - ) - -) - --- Iteration 9 -- -Array -( - [1] => One -) - -Array -( - [1] => One -) - -Array -( - [1] => One -) - --- Iteration 10 -- -Array -( - [test] => is_array -) - -Array -( - [test] => is_array -) - -Array -( - [test] => is_array -) - --- Iteration 11 -- -Array -( - [0] => 0 -) - -Array -( - [0] => 0 -) - -Array -( - [0] => 0 -) - --- Iteration 12 -- -Array -( - [0] => -1 -) - -Array -( - [0] => -1 -) - -Array -( - [0] => -1 -) - --- Iteration 13 -- -Array -( - [0] => 10.5 - [1] => 5.6 -) - -Array -( - [0] => 10.5 - [1] => 5.6 -) - -Array -( - [0] => 10.5 - [1] => 5.6 -) - --- Iteration 14 -- -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - --- Iteration 15 -- -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -Array -( - [0] => string - [1] => test -) - -*** Testing print_r() on object variables *** - --- Iteration 1 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 2 -- -no_member_class Object -( -) - -no_member_class Object -( -) - -no_member_class Object -( -) - --- Iteration 3 -- -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - --- Iteration 4 -- -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - -contains_object_class Object -( - [p] => 30 - [class_object1] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object2] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object3:contains_object_class:private] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [class_object4:protected] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - ) - - [no_member_class_object] => no_member_class Object - ( - ) - - [class_object5] => contains_object_class Object - *RECURSION* -) - --- Iteration 5 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 6 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 7 -- -no_member_class Object -( -) - -no_member_class Object -( -) - -no_member_class Object -( -) - --- Iteration 8 -- -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 -) - --- Iteration 9 -- - - - -** Testing print_r() on objects having circular reference ** -object_class Object -( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - [obj] => object_class Object - ( - [value] => 50 - [public_var1] => 10 - [private_var1:object_class:private] => 20 - [private_var2:object_class:private] => 21 - [protected_var1:protected] => string_1 - [protected_var2:protected] => string_2 - [public_var2] => 11 - [obj] => object_class Object - *RECURSION* - ) - -) - -*** Testing print_r() on resources *** - --- Iteration 1 -- -Resource id #5 -Resource id #5 -Resource id #5 --- Iteration 2 -- -Resource id #6 -Resource id #6 -Resource id #6 -*** Testing print_r() on different combinations of scalar - and non-scalar variables *** - --- Iteration 1 -- -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - -Array -( - [0] => 123 - [1] => -1.2345 - [2] => a -) - --- Iteration 2 -- -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - -Array -( - [0] => d - [1] => Array - ( - [0] => 1 - [1] => 3 - [2] => 5 - ) - - [2] => 1 - [3] => -) - --- Iteration 3 -- -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - -Array -( - [0] => no_member_class Object - ( - ) - - [1] => Array - ( - ) - - [2] => - [3] => 0 -) - --- Iteration 4 -- -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - -Array -( - [0] => -0 - [1] => Where am I? - [2] => Array - ( - [0] => 7 - [1] => 8 - [2] => 9 - ) - - [3] => 1 - [4] => A - [5] => 987654321 -) - --- Iteration 5 -- -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - -Array -( - [0] => - [1] => 20000000000 - [2] => 79.1 - [3] => 4.599998 -) - --- Iteration 6 -- -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -Array -( - [0] => array(1,2,3,4)1.0000002TRUE - [1] => - [2] => 4611333 - [3] => /00\7 -) - -*** Testing print_r() on miscellaneous input arguments *** - --- Iteration 1 -- - - - --- Iteration 2 -- - - - --- Iteration 3 -- - - - --- Iteration 4 -- - - -Done diff --git a/ext/standard/tests/general_functions/print_r_array_circular.phpt b/ext/standard/tests/general_functions/print_r_array_circular.phpt new file mode 100644 index 0000000000000..a8ee05d778853 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_array_circular.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test print_r() function with circular array +--FILE-- + +--EXPECT-- +Array +( + [0] => Array + ( + [0] => Array + *RECURSION* + ) + +) diff --git a/ext/standard/tests/general_functions/print_r_arrays.phpt b/ext/standard/tests/general_functions/print_r_arrays.phpt new file mode 100644 index 0000000000000..edb4aee84291a --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_arrays.phpt @@ -0,0 +1,166 @@ +--TEST-- +Test print_r() function with arrays +--INI-- +precision=14 +--FILE-- + 'One'], + ["test" => "is_array"], + [0], + [-1], + [10.5, 5.6], + ['string', 'test'], +]; + +foreach ($values as $value) { + print_r($value, false); + // $ret_string captures the output + $ret_string = print_r($value, true); + echo "\n$ret_string\n"; +} + +?> +--EXPECT-- +Array +( +) + +Array +( +) + +Array +( + [0] => 1 +) + +Array +( + [0] => 1 +) + +Array +( + [0] => Array + ( + ) + + [1] => Array + ( + ) + +) + +Array +( + [0] => Array + ( + ) + + [1] => Array + ( + ) + +) + +Array +( + [0] => Array + ( + [0] => 1 + [1] => 2 + ) + + [1] => Array + ( + [0] => a + [1] => b + ) + +) + +Array +( + [0] => Array + ( + [0] => 1 + [1] => 2 + ) + + [1] => Array + ( + [0] => a + [1] => b + ) + +) + +Array +( + [1] => One +) + +Array +( + [1] => One +) + +Array +( + [test] => is_array +) + +Array +( + [test] => is_array +) + +Array +( + [0] => 0 +) + +Array +( + [0] => 0 +) + +Array +( + [0] => -1 +) + +Array +( + [0] => -1 +) + +Array +( + [0] => 10.5 + [1] => 5.6 +) + +Array +( + [0] => 10.5 + [1] => 5.6 +) + +Array +( + [0] => string + [1] => test +) + +Array +( + [0] => string + [1] => test +) diff --git a/ext/standard/tests/general_functions/print_r_arrays_whitespace_sensitive.phpt b/ext/standard/tests/general_functions/print_r_arrays_whitespace_sensitive.phpt new file mode 100644 index 0000000000000..87137712064d1 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_arrays_whitespace_sensitive.phpt @@ -0,0 +1,50 @@ +--TEST-- +Test print_r() function with arrays, output has trailing whitespaces +--WHITESPACE_SENSITIVE-- +--FILE-- + null], + ['false' => false], + ['empty' => ''], +]; + +foreach ($values as $value) { + print_r($value, false); + // $ret_string captures the output + $ret_string = print_r($value, true); + echo "\n$ret_string\n"; +} + +?> +--EXPECT-- +Array +( + [null] => +) + +Array +( + [null] => +) + +Array +( + [false] => +) + +Array +( + [false] => +) + +Array +( + [empty] => +) + +Array +( + [empty] => +) diff --git a/ext/standard/tests/general_functions/print_r_bools.phpt b/ext/standard/tests/general_functions/print_r_bools.phpt new file mode 100644 index 0000000000000..f96060ac36eb0 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_bools.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test print_r() function with booleans +--FILE-- + true, + 'false' => false, +]; + +foreach ($values as $key => $value) { + echo "$key:\n"; + print_r($value, false); + // $ret_string captures the output + $ret_string = print_r($value, true); + echo "\n$ret_string\n"; +} + +?> +DONE +--EXPECT-- +true: +1 +1 +false: + + +DONE diff --git a/ext/standard/tests/general_functions/print_r_floats.phpt b/ext/standard/tests/general_functions/print_r_floats.phpt new file mode 100644 index 0000000000000..5da055ce2cb7a --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_floats.phpt @@ -0,0 +1,183 @@ +--TEST-- +Test print_r() function with floats +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +-0 +-0 + +-- Iteration 2 -- +0 +0 + +-- Iteration 3 -- +1.234 +1.234 + +-- Iteration 4 -- +-1.234 +-1.234 + +-- Iteration 5 -- +-2 +-2 + +-- Iteration 6 -- +2 +2 + +-- Iteration 7 -- +-0.5 +-0.5 + +-- Iteration 8 -- +0.567 +0.567 + +-- Iteration 9 -- +-0.00067 +-0.00067 + +-- Iteration 10 -- +-670 +-670 + +-- Iteration 11 -- +670 +670 + +-- Iteration 12 -- +670 +670 + +-- Iteration 13 -- +-0.00410003 +-0.00410003 + +-- Iteration 14 -- +-4100.03 +-4100.03 + +-- Iteration 15 -- +0.004100003 +0.004100003 + +-- Iteration 16 -- +4100.003 +4100.003 + +-- Iteration 17 -- +100000 +100000 + +-- Iteration 18 -- +-100000 +-100000 + +-- Iteration 19 -- +1.0E-5 +1.0E-5 + +-- Iteration 20 -- +-1.0E-5 +-1.0E-5 + +-- Iteration 21 -- +100000 +100000 + +-- Iteration 22 -- +-100000 +-100000 + +-- Iteration 23 -- +100000 +100000 + +-- Iteration 24 -- +-100000 +-100000 + +-- Iteration 25 -- +100000 +100000 + +-- Iteration 26 -- +-100000 +-100000 + +-- Iteration 27 -- +1.0E-5 +1.0E-5 + +-- Iteration 28 -- +-1.0E-5 +-1.0E-5 + +-- Iteration 29 -- +-2147483649 +-2147483649 + +-- Iteration 30 -- +2147483649 +2147483649 + +-- Iteration 31 -- +2147483649 +2147483649 + +-- Iteration 32 -- +-2147483649 +-2147483649 diff --git a/ext/standard/tests/general_functions/print_r_ints.phpt b/ext/standard/tests/general_functions/print_r_ints.phpt new file mode 100644 index 0000000000000..ba1eb9d96be24 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_ints.phpt @@ -0,0 +1,131 @@ +--TEST-- +Test print_r() function with integers +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +0 +0 + +-- Iteration 2 -- +83 +83 + +-- Iteration 3 -- +123000000 +123000000 + +-- Iteration 4 -- +-83 +-83 + +-- Iteration 5 -- +-12300000 +-12300000 + +-- Iteration 6 -- +Array +( + [0] => 1 + [1] => 2 + [2] => 3 + [3] => 4 + [4] => 5 + [5] => 6 + [6] => 7 + [7] => 8 + [8] => 9 + [9] => 10 +) + +Array +( + [0] => 1 + [1] => 2 + [2] => 3 + [3] => 4 + [4] => 5 + [5] => 6 + [6] => 7 + [7] => 8 + [8] => 9 + [9] => 10 +) + + +-- Iteration 7 -- +Array +( + [0] => -1 + [1] => -2 + [2] => -3 + [3] => -4 + [4] => -5 + [5] => -6 + [6] => -7 + [7] => -8 + [8] => -9 + [9] => -10 +) + +Array +( + [0] => -1 + [1] => -2 + [2] => -3 + [3] => -4 + [4] => -5 + [5] => -6 + [6] => -7 + [7] => -8 + [8] => -9 + [9] => -10 +) + + +-- Iteration 8 -- +2147483647 +2147483647 + +-- Iteration 9 -- +2147483648 +2147483648 + +-- Iteration 10 -- +-2147483648 +-2147483648 + +-- Iteration 11 -- +-2147483647 +-2147483647 diff --git a/ext/standard/tests/general_functions/print_r_ints_64bit.phpt b/ext/standard/tests/general_functions/print_r_ints_64bit.phpt new file mode 100644 index 0000000000000..f6f8a56d60782 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_ints_64bit.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test print_r() function with 64 bit integers +--INI-- +precision=14 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +2147483647 +2147483647 +-- Iteration 2 -- +-2147483648 +-2147483648 +-- Iteration 3 -- +2147483647 +2147483647 +-- Iteration 4 -- +-2147483648 +-2147483648 diff --git a/ext/standard/tests/general_functions/print_r_null.phpt b/ext/standard/tests/general_functions/print_r_null.phpt new file mode 100644 index 0000000000000..14a31b1bd8d8d --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_null.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test print_r() function with null +--FILE-- + +DONE +--EXPECT-- +null: + + +DONE diff --git a/ext/standard/tests/general_functions/print_r_object.phpt b/ext/standard/tests/general_functions/print_r_object.phpt new file mode 100644 index 0000000000000..3fe40bc22cfa0 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_object.phpt @@ -0,0 +1,228 @@ +--TEST-- +Test print_r() function +--FILE-- +value = 50; + $this->public_var2 = 11; + $this->private_var2 = 21; + $this->protected_var2 = "string_2"; + } + + public function foo1() { + echo "foo1() is called\n"; + } + protected function foo2() { + echo "foo2() is called\n"; + } + private function foo3() { + echo "foo3() is called\n"; + } +} + +class no_member_class {} + +/* class with member as object of other class */ +#[AllowDynamicProperties] +class contains_object_class +{ + var $p = 30; + var $class_object1; + public $class_object2; + private $class_object3; + protected $class_object4; + var $no_member_class_object; + + public function func() { + echo "func() is called \n"; + } + + function __construct() { + $this->class_object1 = new object_class(); + $this->class_object2 = new object_class(); + $this->class_object3 = $this->class_object1; + $this->class_object4 = $this->class_object2; + $this->no_member_class_object = new no_member_class(); + $this->class_object5 = $this; //recursive reference + } +} + +$objects = [ + new object_class, + new no_member_class, + new contains_object_class, +]; +check_printr($objects); + +?> +--EXPECT-- +*** Testing print_r() on object variables *** + +-- Iteration 1 -- +object_class Object +( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 +) + +object_class Object +( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 +) + + +-- Iteration 2 -- +no_member_class Object +( +) + +no_member_class Object +( +) + + +-- Iteration 3 -- +contains_object_class Object +( + [p] => 30 + [class_object1] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object2] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object3:contains_object_class:private] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object4:protected] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [no_member_class_object] => no_member_class Object + ( + ) + + [class_object5] => contains_object_class Object + *RECURSION* +) + +contains_object_class Object +( + [p] => 30 + [class_object1] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object2] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object3:contains_object_class:private] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [class_object4:protected] => object_class Object + ( + [value] => 50 + [public_var1] => 10 + [private_var1:object_class:private] => 20 + [private_var2:object_class:private] => 21 + [protected_var1:protected] => string_1 + [protected_var2:protected] => string_2 + [public_var2] => 11 + ) + + [no_member_class_object] => no_member_class Object + ( + ) + + [class_object5] => contains_object_class Object + *RECURSION* +) diff --git a/ext/standard/tests/general_functions/print_r_object_circular.phpt b/ext/standard/tests/general_functions/print_r_object_circular.phpt new file mode 100644 index 0000000000000..2930f341ae76c --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_object_circular.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test print_r() function function with circular objects +--FILE-- +obj = $recursion_obj2; +$recursion_obj2->obj = $recursion_obj1; +print_r($recursion_obj2); + +?> +--EXPECT-- +Circular Object +( + [obj] => Circular Object + ( + [obj] => Circular Object + *RECURSION* + ) + +) diff --git a/ext/standard/tests/general_functions/print_r_resources.phpt b/ext/standard/tests/general_functions/print_r_resources.phpt new file mode 100644 index 0000000000000..7a8ea357ac40a --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_resources.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test print_r() function with resources +--FILE-- + +--EXPECT-- +Resource id #1 +Resource id #1 +Resource id #3 +Resource id #3 diff --git a/ext/standard/tests/general_functions/print_r_strings.phpt b/ext/standard/tests/general_functions/print_r_strings.phpt new file mode 100644 index 0000000000000..b01737978cd39 --- /dev/null +++ b/ext/standard/tests/general_functions/print_r_strings.phpt @@ -0,0 +1,61 @@ +--TEST-- +Test print_r() function with strings +--WHITESPACE_SENSITIVE-- +--FILE-- + +--EXPECT-- +-- Iteration 1 -- + + +-- Iteration 2 -- + + +-- Iteration 3 -- +0 +0 +-- Iteration 4 -- +\0 +\0 +-- Iteration 5 -- + + +-- Iteration 6 -- +\t +\t +-- Iteration 7 -- +PHP +PHP +-- Iteration 8 -- +1234 +5678 + 9100"abcda +1234 +5678 + 9100"abcda diff --git a/ext/standard/tests/general_functions/print_r_strings_nul_bytes.phpt b/ext/standard/tests/general_functions/print_r_strings_nul_bytes.phpt new file mode 100644 index 0000000000000000000000000000000000000000..626e88e613b109b5d8e77ac7a066008591868f32 GIT binary patch literal 916 zcmaiyZ)@8y5XSXdpW-li(NK#hZTAPdtS^QKfl$Vp!eAajQRG^yD|wRKrW^h4J=wDx zL)q*X5~q6}-S2dat+T5&V|1;2fZAyjHtuK&MPp>p*1&@fCHQ~`Hy)%lL1=?}Fii#9 z$DllAY%Bvb2!ohA~*8i)bMRPsVbSbgnVE=N-yOp%9f< z)0dRl3?@#6#+k+X>vfh6nklxXs-Qaq9X!}3)J;f18y}R|fi1e^*e)Gflz3^h+jJd8 z##c%RuE7dmHapCeqQ)YyPoY$QZyFqX=7anZW{-b-+;Kh8CrT&%qb}e(Iwd(z(zuGP z+~s?2<|n6TxN`pH?YsBwhO6SH%=h}|ZIz^0-Y^#JjFf6Gb~pidqJqoo)oSqSWIW2E z&7HAzYxm3fkaOPLKkRYg{PFiIu2zQL@5ec%qv`1h@U`g0M;y8A+n4N99OlvE&jBL@ s|8e*vh9fL#QAx{5_yOd9PRDkqgI(+riL@l55*|58q$G&gdHy@)8UKkGw*UYD literal 0 HcmV?d00001 From 5dae1e1dc2ad5c2a9e33c4302175b3809273eeb1 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 4 Mar 2025 02:40:57 +0000 Subject: [PATCH 083/503] Split var_dump tests So that these aren't huge mega tests --- .../tests/general_functions/var_dump.phpt | 1549 ----------------- .../general_functions/var_dump_64bit.phpt | 1549 ----------------- .../var_dump_array_circular.phpt | 20 + .../general_functions/var_dump_arrays.phpt | 99 ++ .../general_functions/var_dump_bools.phpt | 23 + .../general_functions/var_dump_floats.phpt | 76 + .../general_functions/var_dump_ints.phpt | 92 + .../var_dump_ints_32bit.phpt | 33 + .../var_dump_ints_64bit.phpt | 45 + .../general_functions/var_dump_null.phpt | 12 + .../general_functions/var_dump_object.phpt | 181 ++ .../var_dump_object_circular.phpt | 24 + .../general_functions/var_dump_resources.phpt | 18 + .../general_functions/var_dump_strings.phpt | 48 + .../var_dump_strings_nul_bytes.phpt | Bin 0 -> 663 bytes 15 files changed, 671 insertions(+), 3098 deletions(-) delete mode 100644 ext/standard/tests/general_functions/var_dump.phpt delete mode 100644 ext/standard/tests/general_functions/var_dump_64bit.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_array_circular.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_arrays.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_bools.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_floats.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_ints.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_ints_32bit.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_ints_64bit.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_null.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_object.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_object_circular.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_resources.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_strings.phpt create mode 100644 ext/standard/tests/general_functions/var_dump_strings_nul_bytes.phpt diff --git a/ext/standard/tests/general_functions/var_dump.phpt b/ext/standard/tests/general_functions/var_dump.phpt deleted file mode 100644 index 0cbd1fce9c66c..0000000000000 --- a/ext/standard/tests/general_functions/var_dump.phpt +++ /dev/null @@ -1,1549 +0,0 @@ ---TEST-- -Test var_dump() function ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- - 'One'), - array("test" => "is_array"), - array(0), - array(-1), - array(10.5, 5.6), - array("string", "test"), - array('string', 'test'), -); -/* calling check_vardump() to display contents of an array - using var_dump() */ -check_vardump($arrays); - -echo "\n*** Testing var_dump() on object variables ***\n"; -#[AllowDynamicProperties] -class object_class -{ - var $value; - public $public_var1 = 10; - private $private_var1 = 20; - private $private_var2; - protected $protected_var1 = "string_1"; - protected $protected_var2; - - function __construct() { - $this->value = 50; - $this->public_var2 = 11; - $this->private_var2 = 21; - $this->protected_var2 = "string_2"; - } - - public function foo1() { - echo "foo1() is called\n"; - } - protected function foo2() { - echo "foo2() is called\n"; - } - private function foo3() { - echo "foo3() is called\n"; - } -} -/* class with no member */ -class no_member_class { - // no members -} - -/* class with member as object of other class */ -#[AllowDynamicProperties] -class contains_object_class -{ - var $p = 30; - var $class_object1; - public $class_object2; - private $class_object3; - protected $class_object4; - var $no_member_class_object; - - public function func() { - echo "func() is called \n"; - } - - function __construct() { - $this->class_object1 = new object_class(); - $this->class_object2 = new object_class(); - $this->class_object3 = $this->class_object1; - $this->class_object4 = $this->class_object2; - $this->no_member_class_object = new no_member_class(); - $this->class_object5 = $this; //recursive reference - } -} - -/* objects of different classes */ -$obj = new contains_object_class; -$temp_class_obj = new object_class(); - -/* object which is unset */ -$unset_obj = new object_class(); -unset($unset_obj); - -$objects = array ( - new object_class, - new no_member_class, - new contains_object_class, - $obj, - $obj->class_object1, - $obj->class_object2, - $obj->no_member_class_object, - $temp_class_obj, - @$unset_obj -); -/* calling check_vardump() to display contents of the objects - using var_dump() */ -check_vardump($objects); - -echo "\n** Testing var_dump() on objects having circular reference **\n"; -$recursion_obj1 = new object_class(); -$recursion_obj2 = new object_class(); -$recursion_obj1->obj = &$recursion_obj2; //circular reference -$recursion_obj2->obj = &$recursion_obj1; //circular reference -var_dump($recursion_obj2); - -echo "\n*** Testing var_dump() on resources ***\n"; -/* file type resource */ -$file_handle = fopen(__FILE__, "r"); - -/* directory type resource */ -$dir_handle = opendir( __DIR__ ); - -$resources = array ( - $file_handle, - $dir_handle -); -/* calling check_vardump() to display the resource content type - using var_dump() */ -check_vardump($resources); - -echo "\n*** Testing var_dump() on different combinations of scalar - and non-scalar variables ***\n"; -/* a variable which is unset */ -$unset_var = 10.5; -unset($unset_var); - -/* unset file type resource */ -unset($file_handle); - -$variations = array ( - array( 123, -1.2345, "a" ), - array( "d", array(1, 3, 5), true, null), - array( new no_member_class, array(), false, 0 ), - array( -0.00, "Where am I?", array(7,8,9), TRUE, 'A', 987654321 ), - array( @$unset_var, 2.E+10, 100-20.9, 000004.599998 ), //unusual data - array( "array(1,2,3,4)1.0000002TRUE", @$file_handle, 111333.00+45e5, '/00\7') -); -/* calling check_vardump() to display combinations of scalar and - non-scalar variables using var_dump() */ -check_vardump($variations); - -echo "\n*** Testing var_dump() on miscellaneous input arguments ***\n"; -$misc_values = array ( - @$unset_var, - NULL, // NULL argument - @$undef_variable, //undefined variable - null -); -/* calling check_vardump() to display miscellaneous data using var_dump() */ -check_vardump($misc_values); - -echo "\n*** Testing var_dump() on multiple arguments ***\n"; -var_dump( $integers, $floats, $strings, $arrays, $booleans, $resources, - $objects, $misc_values, $variations ); - -/* closing resource handle used */ -closedir($dir_handle); - -echo "Done\n"; -?> ---EXPECTF-- -*** Testing var_dump() on integer variables *** --- Iteration 1 -- -int(0) --- Iteration 2 -- -int(83) --- Iteration 3 -- -int(123000000) --- Iteration 4 -- -int(-83) --- Iteration 5 -- -int(-12300000) --- Iteration 6 -- -array(10) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) - [5]=> - int(6) - [6]=> - int(7) - [7]=> - int(8) - [8]=> - int(9) - [9]=> - int(10) -} --- Iteration 7 -- -array(10) { - [0]=> - int(-1) - [1]=> - int(-2) - [2]=> - int(-3) - [3]=> - int(-4) - [4]=> - int(-5) - [5]=> - int(-6) - [6]=> - int(-7) - [7]=> - int(-8) - [8]=> - int(-9) - [9]=> - int(-10) -} --- Iteration 8 -- -int(2147483647) --- Iteration 9 -- -float(2147483648) --- Iteration 10 -- -float(-2147483648) --- Iteration 11 -- -int(-2147483647) --- Iteration 12 -- -int(2147483647) --- Iteration 13 -- -float(-2147483648) --- Iteration 14 -- -int(2147483647) --- Iteration 15 -- -float(-2147483648) - -*** Testing var_dump() on float variables *** --- Iteration 1 -- -float(-0) --- Iteration 2 -- -float(0) --- Iteration 3 -- -float(1.234) --- Iteration 4 -- -float(-1.234) --- Iteration 5 -- -float(-2) --- Iteration 6 -- -float(2) --- Iteration 7 -- -float(-0.5) --- Iteration 8 -- -float(0.567) --- Iteration 9 -- -float(-0.00067) --- Iteration 10 -- -float(-670) --- Iteration 11 -- -float(670) --- Iteration 12 -- -float(670) --- Iteration 13 -- -float(-0.00410003) --- Iteration 14 -- -float(-4100.03) --- Iteration 15 -- -float(0.004100003) --- Iteration 16 -- -float(4100.003) --- Iteration 17 -- -float(100000) --- Iteration 18 -- -float(-100000) --- Iteration 19 -- -float(1.0E-5) --- Iteration 20 -- -float(-1.0E-5) --- Iteration 21 -- -float(100000) --- Iteration 22 -- -float(-100000) --- Iteration 23 -- -float(100000) --- Iteration 24 -- -float(-100000) --- Iteration 25 -- -float(100000) --- Iteration 26 -- -float(-100000) --- Iteration 27 -- -float(1.0E-5) --- Iteration 28 -- -float(-1.0E-5) --- Iteration 29 -- -float(-2147483649) --- Iteration 30 -- -float(2147483649) --- Iteration 31 -- -float(2147483649) --- Iteration 32 -- -float(-2147483649) - -*** Testing var_dump() on string variables *** --- Iteration 1 -- -string(0) "" --- Iteration 2 -- -string(0) "" --- Iteration 3 -- -string(1) " " --- Iteration 4 -- -string(1) " " --- Iteration 5 -- -string(1) "0" --- Iteration 6 -- -string(1) "%0" --- Iteration 7 -- -string(2) "\0" --- Iteration 8 -- -string(1) " " --- Iteration 9 -- -string(2) "\t" --- Iteration 10 -- -string(3) "PHP" --- Iteration 11 -- -string(3) "PHP" --- Iteration 12 -- -string(29) "abcd%0n1234%005678%000efgh\xijkl" --- Iteration 13 -- -string(34) "abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz" --- Iteration 14 -- -string(22) "1234 -5678 - 9100"abcda" - -*** Testing var_dump() on boolean variables *** --- Iteration 1 -- -bool(true) --- Iteration 2 -- -bool(false) --- Iteration 3 -- -bool(true) --- Iteration 4 -- -bool(false) - -*** Testing var_dump() on array variables *** --- Iteration 1 -- -array(0) { -} --- Iteration 2 -- -array(1) { - [0]=> - NULL -} --- Iteration 3 -- -array(1) { - [0]=> - NULL -} --- Iteration 4 -- -array(1) { - [0]=> - bool(true) -} --- Iteration 5 -- -array(1) { - [0]=> - string(0) "" -} --- Iteration 6 -- -array(1) { - [0]=> - string(0) "" -} --- Iteration 7 -- -array(2) { - [0]=> - array(0) { - } - [1]=> - array(0) { - } -} --- Iteration 8 -- -array(2) { - [0]=> - array(2) { - [0]=> - int(1) - [1]=> - int(2) - } - [1]=> - array(2) { - [0]=> - string(1) "a" - [1]=> - string(1) "b" - } -} --- Iteration 9 -- -array(1) { - [1]=> - string(3) "One" -} --- Iteration 10 -- -array(1) { - ["test"]=> - string(8) "is_array" -} --- Iteration 11 -- -array(1) { - [0]=> - int(0) -} --- Iteration 12 -- -array(1) { - [0]=> - int(-1) -} --- Iteration 13 -- -array(2) { - [0]=> - float(10.5) - [1]=> - float(5.6) -} --- Iteration 14 -- -array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" -} --- Iteration 15 -- -array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" -} - -*** Testing var_dump() on object variables *** --- Iteration 1 -- -object(object_class)#6 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 2 -- -object(no_member_class)#7 (0) { -} --- Iteration 3 -- -object(contains_object_class)#8 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#11 (0) { - } - ["class_object5"]=> - *RECURSION* -} --- Iteration 4 -- -object(contains_object_class)#1 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#4 (0) { - } - ["class_object5"]=> - *RECURSION* -} --- Iteration 5 -- -object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 6 -- -object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 7 -- -object(no_member_class)#4 (0) { -} --- Iteration 8 -- -object(object_class)#5 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 9 -- -NULL - -** Testing var_dump() on objects having circular reference ** -object(object_class)#13 (8) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - ["obj"]=> - &object(object_class)#12 (8) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - ["obj"]=> - *RECURSION* - } -} - -*** Testing var_dump() on resources *** --- Iteration 1 -- -resource(%d) of type (stream) --- Iteration 2 -- -resource(%d) of type (stream) - -*** Testing var_dump() on different combinations of scalar - and non-scalar variables *** --- Iteration 1 -- -array(3) { - [0]=> - int(123) - [1]=> - float(-1.2345) - [2]=> - string(1) "a" -} --- Iteration 2 -- -array(4) { - [0]=> - string(1) "d" - [1]=> - array(3) { - [0]=> - int(1) - [1]=> - int(3) - [2]=> - int(5) - } - [2]=> - bool(true) - [3]=> - NULL -} --- Iteration 3 -- -array(4) { - [0]=> - object(no_member_class)#14 (0) { - } - [1]=> - array(0) { - } - [2]=> - bool(false) - [3]=> - int(0) -} --- Iteration 4 -- -array(6) { - [0]=> - float(-0) - [1]=> - string(11) "Where am I?" - [2]=> - array(3) { - [0]=> - int(7) - [1]=> - int(8) - [2]=> - int(9) - } - [3]=> - bool(true) - [4]=> - string(1) "A" - [5]=> - int(987654321) -} --- Iteration 5 -- -array(4) { - [0]=> - NULL - [1]=> - float(20000000000) - [2]=> - float(79.1) - [3]=> - float(4.599998) -} --- Iteration 6 -- -array(4) { - [0]=> - string(27) "array(1,2,3,4)1.0000002TRUE" - [1]=> - NULL - [2]=> - float(4611333) - [3]=> - string(5) "/00\7" -} - -*** Testing var_dump() on miscellaneous input arguments *** --- Iteration 1 -- -NULL --- Iteration 2 -- -NULL --- Iteration 3 -- -NULL --- Iteration 4 -- -NULL - -*** Testing var_dump() on multiple arguments *** -array(15) { - [0]=> - int(0) - [1]=> - int(83) - [2]=> - int(123000000) - [3]=> - int(-83) - [4]=> - int(-12300000) - [5]=> - array(10) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) - [5]=> - int(6) - [6]=> - int(7) - [7]=> - int(8) - [8]=> - int(9) - [9]=> - int(10) - } - [6]=> - array(10) { - [0]=> - int(-1) - [1]=> - int(-2) - [2]=> - int(-3) - [3]=> - int(-4) - [4]=> - int(-5) - [5]=> - int(-6) - [6]=> - int(-7) - [7]=> - int(-8) - [8]=> - int(-9) - [9]=> - int(-10) - } - [7]=> - int(2147483647) - [8]=> - float(2147483648) - [9]=> - float(-2147483648) - [10]=> - int(-2147483647) - [11]=> - int(2147483647) - [12]=> - float(-2147483648) - [13]=> - int(2147483647) - [14]=> - float(-2147483648) -} -array(32) { - [0]=> - float(-0) - [1]=> - float(0) - [2]=> - float(1.234) - [3]=> - float(-1.234) - [4]=> - float(-2) - [5]=> - float(2) - [6]=> - float(-0.5) - [7]=> - float(0.567) - [8]=> - float(-0.00067) - [9]=> - float(-670) - [10]=> - float(670) - [11]=> - float(670) - [12]=> - float(-0.00410003) - [13]=> - float(-4100.03) - [14]=> - float(0.004100003) - [15]=> - float(4100.003) - [16]=> - float(100000) - [17]=> - float(-100000) - [18]=> - float(1.0E-5) - [19]=> - float(-1.0E-5) - [20]=> - float(100000) - [21]=> - float(-100000) - [22]=> - float(100000) - [23]=> - float(-100000) - [24]=> - float(100000) - [25]=> - float(-100000) - [26]=> - float(1.0E-5) - [27]=> - float(-1.0E-5) - [28]=> - float(-2147483649) - [29]=> - float(2147483649) - [30]=> - float(2147483649) - [31]=> - float(-2147483649) -} -array(14) { - [0]=> - string(0) "" - [1]=> - string(0) "" - [2]=> - string(1) " " - [3]=> - string(1) " " - [4]=> - string(1) "0" - [5]=> - string(1) "%0" - [6]=> - string(2) "\0" - [7]=> - string(1) " " - [8]=> - string(2) "\t" - [9]=> - string(3) "PHP" - [10]=> - string(3) "PHP" - [11]=> - string(29) "abcd%0n1234%005678%000efgh\xijkl" - [12]=> - string(34) "abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz" - [13]=> - string(22) "1234 -5678 - 9100"abcda" -} -array(15) { - [0]=> - array(0) { - } - [1]=> - array(1) { - [0]=> - NULL - } - [2]=> - array(1) { - [0]=> - NULL - } - [3]=> - array(1) { - [0]=> - bool(true) - } - [4]=> - array(1) { - [0]=> - string(0) "" - } - [5]=> - array(1) { - [0]=> - string(0) "" - } - [6]=> - array(2) { - [0]=> - array(0) { - } - [1]=> - array(0) { - } - } - [7]=> - array(2) { - [0]=> - array(2) { - [0]=> - int(1) - [1]=> - int(2) - } - [1]=> - array(2) { - [0]=> - string(1) "a" - [1]=> - string(1) "b" - } - } - [8]=> - array(1) { - [1]=> - string(3) "One" - } - [9]=> - array(1) { - ["test"]=> - string(8) "is_array" - } - [10]=> - array(1) { - [0]=> - int(0) - } - [11]=> - array(1) { - [0]=> - int(-1) - } - [12]=> - array(2) { - [0]=> - float(10.5) - [1]=> - float(5.6) - } - [13]=> - array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" - } - [14]=> - array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" - } -} -array(4) { - [0]=> - bool(true) - [1]=> - bool(false) - [2]=> - bool(true) - [3]=> - bool(false) -} -array(2) { - [0]=> - resource(%d) of type (stream) - [1]=> - resource(%d) of type (stream) -} -array(9) { - [0]=> - object(object_class)#6 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [1]=> - object(no_member_class)#7 (0) { - } - [2]=> - object(contains_object_class)#8 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#11 (0) { - } - ["class_object5"]=> - *RECURSION* - } - [3]=> - object(contains_object_class)#1 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#4 (0) { - } - ["class_object5"]=> - *RECURSION* - } - [4]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [5]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [6]=> - object(no_member_class)#4 (0) { - } - [7]=> - object(object_class)#5 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [8]=> - NULL -} -array(4) { - [0]=> - NULL - [1]=> - NULL - [2]=> - NULL - [3]=> - NULL -} -array(6) { - [0]=> - array(3) { - [0]=> - int(123) - [1]=> - float(-1.2345) - [2]=> - string(1) "a" - } - [1]=> - array(4) { - [0]=> - string(1) "d" - [1]=> - array(3) { - [0]=> - int(1) - [1]=> - int(3) - [2]=> - int(5) - } - [2]=> - bool(true) - [3]=> - NULL - } - [2]=> - array(4) { - [0]=> - object(no_member_class)#14 (0) { - } - [1]=> - array(0) { - } - [2]=> - bool(false) - [3]=> - int(0) - } - [3]=> - array(6) { - [0]=> - float(-0) - [1]=> - string(11) "Where am I?" - [2]=> - array(3) { - [0]=> - int(7) - [1]=> - int(8) - [2]=> - int(9) - } - [3]=> - bool(true) - [4]=> - string(1) "A" - [5]=> - int(987654321) - } - [4]=> - array(4) { - [0]=> - NULL - [1]=> - float(20000000000) - [2]=> - float(79.1) - [3]=> - float(4.599998) - } - [5]=> - array(4) { - [0]=> - string(27) "array(1,2,3,4)1.0000002TRUE" - [1]=> - NULL - [2]=> - float(4611333) - [3]=> - string(5) "/00\7" - } -} -Done diff --git a/ext/standard/tests/general_functions/var_dump_64bit.phpt b/ext/standard/tests/general_functions/var_dump_64bit.phpt deleted file mode 100644 index cbf9c003bdb92..0000000000000 --- a/ext/standard/tests/general_functions/var_dump_64bit.phpt +++ /dev/null @@ -1,1549 +0,0 @@ ---TEST-- -Test var_dump() function ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- - 'One'), - array("test" => "is_array"), - array(0), - array(-1), - array(10.5, 5.6), - array("string", "test"), - array('string', 'test'), -); -/* calling check_vardump() to display contents of an array - using var_dump() */ -check_vardump($arrays); - -echo "\n*** Testing var_dump() on object variables ***\n"; -#[AllowDynamicProperties] -class object_class -{ - var $value; - public $public_var1 = 10; - private $private_var1 = 20; - private $private_var2; - protected $protected_var1 = "string_1"; - protected $protected_var2; - - function __construct ( ) { - $this->value = 50; - $this->public_var2 = 11; - $this->private_var2 = 21; - $this->protected_var2 = "string_2"; - } - - public function foo1() { - echo "foo1() is called\n"; - } - protected function foo2() { - echo "foo2() is called\n"; - } - private function foo3() { - echo "foo3() is called\n"; - } -} -/* class with no member */ -class no_member_class { - // no members -} - -/* class with member as object of other class */ -#[AllowDynamicProperties] -class contains_object_class -{ - var $p = 30; - var $class_object1; - public $class_object2; - private $class_object3; - protected $class_object4; - var $no_member_class_object; - - public function func() { - echo "func() is called \n"; - } - - function __construct () { - $this->class_object1 = new object_class(); - $this->class_object2 = new object_class(); - $this->class_object3 = $this->class_object1; - $this->class_object4 = $this->class_object2; - $this->no_member_class_object = new no_member_class(); - $this->class_object5 = $this; //recursive reference - } -} - -/* objects of different classes */ -$obj = new contains_object_class; -$temp_class_obj = new object_class(); - -/* object which is unset */ -$unset_obj = new object_class(); -unset($unset_obj); - -$objects = array ( - new object_class, - new no_member_class, - new contains_object_class, - $obj, - $obj->class_object1, - $obj->class_object2, - $obj->no_member_class_object, - $temp_class_obj, - @$unset_obj -); -/* calling check_vardump() to display contents of the objects - using var_dump() */ -check_vardump($objects); - -echo "\n** Testing var_dump() on objects having circular reference **\n"; -$recursion_obj1 = new object_class(); -$recursion_obj2 = new object_class(); -$recursion_obj1->obj = &$recursion_obj2; //circular reference -$recursion_obj2->obj = &$recursion_obj1; //circular reference -var_dump($recursion_obj2); - -echo "\n*** Testing var_dump() on resources ***\n"; -/* file type resource */ -$file_handle = fopen(__FILE__, "r"); - -/* directory type resource */ -$dir_handle = opendir( __DIR__ ); - -$resources = array ( - $file_handle, - $dir_handle -); -/* calling check_vardump() to display the resource content type - using var_dump() */ -check_vardump($resources); - -echo "\n*** Testing var_dump() on different combinations of scalar - and non-scalar variables ***\n"; -/* a variable which is unset */ -$unset_var = 10.5; -unset($unset_var); - -/* unset file type resource */ -unset($file_handle); - -$variations = array ( - array( 123, -1.2345, "a" ), - array( "d", array(1, 3, 5), true, null), - array( new no_member_class, array(), false, 0 ), - array( -0.00, "Where am I?", array(7,8,9), TRUE, 'A', 987654321 ), - array( @$unset_var, 2.E+10, 100-20.9, 000004.599998 ), //unusual data - array( "array(1,2,3,4)1.0000002TRUE", @$file_handle, 111333.00+45e5, '/00\7') -); -/* calling check_vardump() to display combinations of scalar and - non-scalar variables using var_dump() */ -check_vardump($variations); - -echo "\n*** Testing var_dump() on miscellaneous input arguments ***\n"; -$misc_values = array ( - @$unset_var, - NULL, // NULL argument - @$undef_variable, //undefined variable - null -); -/* calling check_vardump() to display miscellaneous data using var_dump() */ -check_vardump($misc_values); - -echo "\n*** Testing var_dump() on multiple arguments ***\n"; -var_dump( $integers, $floats, $strings, $arrays, $booleans, $resources, - $objects, $misc_values, $variations ); - -/* closing resource handle used */ -closedir($dir_handle); - -echo "Done\n"; -?> ---EXPECTF-- -*** Testing var_dump() on integer variables *** --- Iteration 1 -- -int(0) --- Iteration 2 -- -int(83) --- Iteration 3 -- -int(123000000) --- Iteration 4 -- -int(-83) --- Iteration 5 -- -int(-12300000) --- Iteration 6 -- -array(10) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) - [5]=> - int(6) - [6]=> - int(7) - [7]=> - int(8) - [8]=> - int(9) - [9]=> - int(10) -} --- Iteration 7 -- -array(10) { - [0]=> - int(-1) - [1]=> - int(-2) - [2]=> - int(-3) - [3]=> - int(-4) - [4]=> - int(-5) - [5]=> - int(-6) - [6]=> - int(-7) - [7]=> - int(-8) - [8]=> - int(-9) - [9]=> - int(-10) -} --- Iteration 8 -- -int(2147483647) --- Iteration 9 -- -int(2147483648) --- Iteration 10 -- -int(-2147483648) --- Iteration 11 -- -int(-2147483647) --- Iteration 12 -- -int(2147483647) --- Iteration 13 -- -int(-2147483648) --- Iteration 14 -- -int(2147483647) --- Iteration 15 -- -int(-2147483648) - -*** Testing var_dump() on float variables *** --- Iteration 1 -- -float(-0) --- Iteration 2 -- -float(0) --- Iteration 3 -- -float(1.234) --- Iteration 4 -- -float(-1.234) --- Iteration 5 -- -float(-2) --- Iteration 6 -- -float(2) --- Iteration 7 -- -float(-0.5) --- Iteration 8 -- -float(0.567) --- Iteration 9 -- -float(-0.00067) --- Iteration 10 -- -float(-670) --- Iteration 11 -- -float(670) --- Iteration 12 -- -float(670) --- Iteration 13 -- -float(-0.00410003) --- Iteration 14 -- -float(-4100.03) --- Iteration 15 -- -float(0.004100003) --- Iteration 16 -- -float(4100.003) --- Iteration 17 -- -float(100000) --- Iteration 18 -- -float(-100000) --- Iteration 19 -- -float(1.0E-5) --- Iteration 20 -- -float(-1.0E-5) --- Iteration 21 -- -float(100000) --- Iteration 22 -- -float(-100000) --- Iteration 23 -- -float(100000) --- Iteration 24 -- -float(-100000) --- Iteration 25 -- -float(100000) --- Iteration 26 -- -float(-100000) --- Iteration 27 -- -float(1.0E-5) --- Iteration 28 -- -float(-1.0E-5) --- Iteration 29 -- -int(-2147483649) --- Iteration 30 -- -int(2147483649) --- Iteration 31 -- -int(2147483649) --- Iteration 32 -- -int(-2147483649) - -*** Testing var_dump() on string variables *** --- Iteration 1 -- -string(0) "" --- Iteration 2 -- -string(0) "" --- Iteration 3 -- -string(1) " " --- Iteration 4 -- -string(1) " " --- Iteration 5 -- -string(1) "0" --- Iteration 6 -- -string(1) "%0" --- Iteration 7 -- -string(2) "\0" --- Iteration 8 -- -string(1) " " --- Iteration 9 -- -string(2) "\t" --- Iteration 10 -- -string(3) "PHP" --- Iteration 11 -- -string(3) "PHP" --- Iteration 12 -- -string(29) "abcd%0n1234%005678%000efgh\xijkl" --- Iteration 13 -- -string(34) "abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz" --- Iteration 14 -- -string(22) "1234 -5678 - 9100"abcda" - -*** Testing var_dump() on boolean variables *** --- Iteration 1 -- -bool(true) --- Iteration 2 -- -bool(false) --- Iteration 3 -- -bool(true) --- Iteration 4 -- -bool(false) - -*** Testing var_dump() on array variables *** --- Iteration 1 -- -array(0) { -} --- Iteration 2 -- -array(1) { - [0]=> - NULL -} --- Iteration 3 -- -array(1) { - [0]=> - NULL -} --- Iteration 4 -- -array(1) { - [0]=> - bool(true) -} --- Iteration 5 -- -array(1) { - [0]=> - string(0) "" -} --- Iteration 6 -- -array(1) { - [0]=> - string(0) "" -} --- Iteration 7 -- -array(2) { - [0]=> - array(0) { - } - [1]=> - array(0) { - } -} --- Iteration 8 -- -array(2) { - [0]=> - array(2) { - [0]=> - int(1) - [1]=> - int(2) - } - [1]=> - array(2) { - [0]=> - string(1) "a" - [1]=> - string(1) "b" - } -} --- Iteration 9 -- -array(1) { - [1]=> - string(3) "One" -} --- Iteration 10 -- -array(1) { - ["test"]=> - string(8) "is_array" -} --- Iteration 11 -- -array(1) { - [0]=> - int(0) -} --- Iteration 12 -- -array(1) { - [0]=> - int(-1) -} --- Iteration 13 -- -array(2) { - [0]=> - float(10.5) - [1]=> - float(5.6) -} --- Iteration 14 -- -array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" -} --- Iteration 15 -- -array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" -} - -*** Testing var_dump() on object variables *** --- Iteration 1 -- -object(object_class)#6 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 2 -- -object(no_member_class)#7 (0) { -} --- Iteration 3 -- -object(contains_object_class)#8 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#11 (0) { - } - ["class_object5"]=> - *RECURSION* -} --- Iteration 4 -- -object(contains_object_class)#1 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#4 (0) { - } - ["class_object5"]=> - *RECURSION* -} --- Iteration 5 -- -object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 6 -- -object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 7 -- -object(no_member_class)#4 (0) { -} --- Iteration 8 -- -object(object_class)#5 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) -} --- Iteration 9 -- -NULL - -** Testing var_dump() on objects having circular reference ** -object(object_class)#13 (8) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - ["obj"]=> - &object(object_class)#12 (8) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - ["obj"]=> - *RECURSION* - } -} - -*** Testing var_dump() on resources *** --- Iteration 1 -- -resource(5) of type (stream) --- Iteration 2 -- -resource(6) of type (stream) - -*** Testing var_dump() on different combinations of scalar - and non-scalar variables *** --- Iteration 1 -- -array(3) { - [0]=> - int(123) - [1]=> - float(-1.2345) - [2]=> - string(1) "a" -} --- Iteration 2 -- -array(4) { - [0]=> - string(1) "d" - [1]=> - array(3) { - [0]=> - int(1) - [1]=> - int(3) - [2]=> - int(5) - } - [2]=> - bool(true) - [3]=> - NULL -} --- Iteration 3 -- -array(4) { - [0]=> - object(no_member_class)#14 (0) { - } - [1]=> - array(0) { - } - [2]=> - bool(false) - [3]=> - int(0) -} --- Iteration 4 -- -array(6) { - [0]=> - float(-0) - [1]=> - string(11) "Where am I?" - [2]=> - array(3) { - [0]=> - int(7) - [1]=> - int(8) - [2]=> - int(9) - } - [3]=> - bool(true) - [4]=> - string(1) "A" - [5]=> - int(987654321) -} --- Iteration 5 -- -array(4) { - [0]=> - NULL - [1]=> - float(20000000000) - [2]=> - float(79.1) - [3]=> - float(4.599998) -} --- Iteration 6 -- -array(4) { - [0]=> - string(27) "array(1,2,3,4)1.0000002TRUE" - [1]=> - NULL - [2]=> - float(4611333) - [3]=> - string(5) "/00\7" -} - -*** Testing var_dump() on miscellaneous input arguments *** --- Iteration 1 -- -NULL --- Iteration 2 -- -NULL --- Iteration 3 -- -NULL --- Iteration 4 -- -NULL - -*** Testing var_dump() on multiple arguments *** -array(15) { - [0]=> - int(0) - [1]=> - int(83) - [2]=> - int(123000000) - [3]=> - int(-83) - [4]=> - int(-12300000) - [5]=> - array(10) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) - [4]=> - int(5) - [5]=> - int(6) - [6]=> - int(7) - [7]=> - int(8) - [8]=> - int(9) - [9]=> - int(10) - } - [6]=> - array(10) { - [0]=> - int(-1) - [1]=> - int(-2) - [2]=> - int(-3) - [3]=> - int(-4) - [4]=> - int(-5) - [5]=> - int(-6) - [6]=> - int(-7) - [7]=> - int(-8) - [8]=> - int(-9) - [9]=> - int(-10) - } - [7]=> - int(2147483647) - [8]=> - int(2147483648) - [9]=> - int(-2147483648) - [10]=> - int(-2147483647) - [11]=> - int(2147483647) - [12]=> - int(-2147483648) - [13]=> - int(2147483647) - [14]=> - int(-2147483648) -} -array(32) { - [0]=> - float(-0) - [1]=> - float(0) - [2]=> - float(1.234) - [3]=> - float(-1.234) - [4]=> - float(-2) - [5]=> - float(2) - [6]=> - float(-0.5) - [7]=> - float(0.567) - [8]=> - float(-0.00067) - [9]=> - float(-670) - [10]=> - float(670) - [11]=> - float(670) - [12]=> - float(-0.00410003) - [13]=> - float(-4100.03) - [14]=> - float(0.004100003) - [15]=> - float(4100.003) - [16]=> - float(100000) - [17]=> - float(-100000) - [18]=> - float(1.0E-5) - [19]=> - float(-1.0E-5) - [20]=> - float(100000) - [21]=> - float(-100000) - [22]=> - float(100000) - [23]=> - float(-100000) - [24]=> - float(100000) - [25]=> - float(-100000) - [26]=> - float(1.0E-5) - [27]=> - float(-1.0E-5) - [28]=> - int(-2147483649) - [29]=> - int(2147483649) - [30]=> - int(2147483649) - [31]=> - int(-2147483649) -} -array(14) { - [0]=> - string(0) "" - [1]=> - string(0) "" - [2]=> - string(1) " " - [3]=> - string(1) " " - [4]=> - string(1) "0" - [5]=> - string(1) "%0" - [6]=> - string(2) "\0" - [7]=> - string(1) " " - [8]=> - string(2) "\t" - [9]=> - string(3) "PHP" - [10]=> - string(3) "PHP" - [11]=> - string(29) "abcd%0n1234%005678%000efgh\xijkl" - [12]=> - string(34) "abcd%0efgh%0ijkl%0mnop%00qrst%0uvwx%00yz" - [13]=> - string(22) "1234 -5678 - 9100"abcda" -} -array(15) { - [0]=> - array(0) { - } - [1]=> - array(1) { - [0]=> - NULL - } - [2]=> - array(1) { - [0]=> - NULL - } - [3]=> - array(1) { - [0]=> - bool(true) - } - [4]=> - array(1) { - [0]=> - string(0) "" - } - [5]=> - array(1) { - [0]=> - string(0) "" - } - [6]=> - array(2) { - [0]=> - array(0) { - } - [1]=> - array(0) { - } - } - [7]=> - array(2) { - [0]=> - array(2) { - [0]=> - int(1) - [1]=> - int(2) - } - [1]=> - array(2) { - [0]=> - string(1) "a" - [1]=> - string(1) "b" - } - } - [8]=> - array(1) { - [1]=> - string(3) "One" - } - [9]=> - array(1) { - ["test"]=> - string(8) "is_array" - } - [10]=> - array(1) { - [0]=> - int(0) - } - [11]=> - array(1) { - [0]=> - int(-1) - } - [12]=> - array(2) { - [0]=> - float(10.5) - [1]=> - float(5.6) - } - [13]=> - array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" - } - [14]=> - array(2) { - [0]=> - string(6) "string" - [1]=> - string(4) "test" - } -} -array(4) { - [0]=> - bool(true) - [1]=> - bool(false) - [2]=> - bool(true) - [3]=> - bool(false) -} -array(2) { - [0]=> - resource(5) of type (stream) - [1]=> - resource(6) of type (stream) -} -array(9) { - [0]=> - object(object_class)#6 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [1]=> - object(no_member_class)#7 (0) { - } - [2]=> - object(contains_object_class)#8 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#9 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#10 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#11 (0) { - } - ["class_object5"]=> - *RECURSION* - } - [3]=> - object(contains_object_class)#1 (7) { - ["p"]=> - int(30) - ["class_object1"]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object2"]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object3":"contains_object_class":private]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["class_object4":protected]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - ["no_member_class_object"]=> - object(no_member_class)#4 (0) { - } - ["class_object5"]=> - *RECURSION* - } - [4]=> - object(object_class)#2 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [5]=> - object(object_class)#3 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [6]=> - object(no_member_class)#4 (0) { - } - [7]=> - object(object_class)#5 (7) { - ["value"]=> - int(50) - ["public_var1"]=> - int(10) - ["private_var1":"object_class":private]=> - int(20) - ["private_var2":"object_class":private]=> - int(21) - ["protected_var1":protected]=> - string(8) "string_1" - ["protected_var2":protected]=> - string(8) "string_2" - ["public_var2"]=> - int(11) - } - [8]=> - NULL -} -array(4) { - [0]=> - NULL - [1]=> - NULL - [2]=> - NULL - [3]=> - NULL -} -array(6) { - [0]=> - array(3) { - [0]=> - int(123) - [1]=> - float(-1.2345) - [2]=> - string(1) "a" - } - [1]=> - array(4) { - [0]=> - string(1) "d" - [1]=> - array(3) { - [0]=> - int(1) - [1]=> - int(3) - [2]=> - int(5) - } - [2]=> - bool(true) - [3]=> - NULL - } - [2]=> - array(4) { - [0]=> - object(no_member_class)#14 (0) { - } - [1]=> - array(0) { - } - [2]=> - bool(false) - [3]=> - int(0) - } - [3]=> - array(6) { - [0]=> - float(-0) - [1]=> - string(11) "Where am I?" - [2]=> - array(3) { - [0]=> - int(7) - [1]=> - int(8) - [2]=> - int(9) - } - [3]=> - bool(true) - [4]=> - string(1) "A" - [5]=> - int(987654321) - } - [4]=> - array(4) { - [0]=> - NULL - [1]=> - float(20000000000) - [2]=> - float(79.1) - [3]=> - float(4.599998) - } - [5]=> - array(4) { - [0]=> - string(27) "array(1,2,3,4)1.0000002TRUE" - [1]=> - NULL - [2]=> - float(4611333) - [3]=> - string(5) "/00\7" - } -} -Done diff --git a/ext/standard/tests/general_functions/var_dump_array_circular.phpt b/ext/standard/tests/general_functions/var_dump_array_circular.phpt new file mode 100644 index 0000000000000..5bee8eb481358 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_array_circular.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test var_dump() function with circular array +--FILE-- + +--EXPECT-- +array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } +} diff --git a/ext/standard/tests/general_functions/var_dump_arrays.phpt b/ext/standard/tests/general_functions/var_dump_arrays.phpt new file mode 100644 index 0000000000000..7b75e75e07cca --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_arrays.phpt @@ -0,0 +1,99 @@ +--TEST-- +Test var_dump() function with arrays +--INI-- +precision=14 +--FILE-- + 'One'], + ["test" => "is_array"], + [0], + [-1], + [10.5, 5.6], + ['string', 'test'], +]; + +foreach ($values as $value) { + var_dump($value); +} + +?> +--EXPECT-- +array(0) { +} +array(1) { + [0]=> + NULL +} +array(1) { + [0]=> + bool(false) +} +array(1) { + [0]=> + bool(true) +} +array(1) { + [0]=> + string(0) "" +} +array(2) { + [0]=> + array(0) { + } + [1]=> + array(0) { + } +} +array(2) { + [0]=> + array(2) { + [0]=> + int(1) + [1]=> + int(2) + } + [1]=> + array(2) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + } +} +array(1) { + [1]=> + string(3) "One" +} +array(1) { + ["test"]=> + string(8) "is_array" +} +array(1) { + [0]=> + int(0) +} +array(1) { + [0]=> + int(-1) +} +array(2) { + [0]=> + float(10.5) + [1]=> + float(5.6) +} +array(2) { + [0]=> + string(6) "string" + [1]=> + string(4) "test" +} diff --git a/ext/standard/tests/general_functions/var_dump_bools.phpt b/ext/standard/tests/general_functions/var_dump_bools.phpt new file mode 100644 index 0000000000000..034a8d7a2af48 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_bools.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test var_dump() function with booleans +--FILE-- + true, + 'false' => false, +]; + +foreach ($values as $key => $value) { + echo "$key:\n"; + var_dump($value); +} + +?> +DONE +--EXPECT-- +true: +bool(true) +false: +bool(false) +DONE diff --git a/ext/standard/tests/general_functions/var_dump_floats.phpt b/ext/standard/tests/general_functions/var_dump_floats.phpt new file mode 100644 index 0000000000000..9ded48b1d3b17 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_floats.phpt @@ -0,0 +1,76 @@ +--TEST-- +Test var_dump() function with floats +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +float(-0) +-- Iteration 2 -- +float(0) +-- Iteration 3 -- +float(1.234) +-- Iteration 4 -- +float(-1.234) +-- Iteration 5 -- +float(-2) +-- Iteration 6 -- +float(2) +-- Iteration 7 -- +float(-0.5) +-- Iteration 8 -- +float(0.567) +-- Iteration 9 -- +float(-0.00067) +-- Iteration 10 -- +float(670) +-- Iteration 11 -- +float(-0.00410003) +-- Iteration 12 -- +float(0.004100003) +-- Iteration 13 -- +float(100000) +-- Iteration 14 -- +float(-100000) +-- Iteration 15 -- +float(1.0E-5) +-- Iteration 16 -- +float(-1.0E-5) +-- Iteration 17 -- +float(100000) +-- Iteration 18 -- +float(-100000) diff --git a/ext/standard/tests/general_functions/var_dump_ints.phpt b/ext/standard/tests/general_functions/var_dump_ints.phpt new file mode 100644 index 0000000000000..b9146c10b2aa0 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_ints.phpt @@ -0,0 +1,92 @@ +--TEST-- +Test var_dump() function with integers +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +int(0) +-- Iteration 2 -- +int(83) +-- Iteration 3 -- +int(123000000) +-- Iteration 4 -- +int(-83) +-- Iteration 5 -- +int(-12300000) +-- Iteration 6 -- +array(10) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + [3]=> + int(4) + [4]=> + int(5) + [5]=> + int(6) + [6]=> + int(7) + [7]=> + int(8) + [8]=> + int(9) + [9]=> + int(10) +} +-- Iteration 7 -- +array(10) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + int(-3) + [3]=> + int(-4) + [4]=> + int(-5) + [5]=> + int(-6) + [6]=> + int(-7) + [7]=> + int(-8) + [8]=> + int(-9) + [9]=> + int(-10) +} +-- Iteration 8 -- +int(2147483647) +-- Iteration 9 -- +int(-2147483647) diff --git a/ext/standard/tests/general_functions/var_dump_ints_32bit.phpt b/ext/standard/tests/general_functions/var_dump_ints_32bit.phpt new file mode 100644 index 0000000000000..7cc818cfb22eb --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_ints_32bit.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test var_dump() function with 32 bit integers +--INI-- +precision=14 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +float(2147483648) +-- Iteration 2 -- +float(-2147483648) diff --git a/ext/standard/tests/general_functions/var_dump_ints_64bit.phpt b/ext/standard/tests/general_functions/var_dump_ints_64bit.phpt new file mode 100644 index 0000000000000..cb01803c163bc --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_ints_64bit.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test var_dump() function with 64 bit integers +--INI-- +precision=14 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +int(2147483647) +-- Iteration 2 -- +int(-2147483648) +-- Iteration 3 -- +int(2147483647) +-- Iteration 4 -- +int(-2147483648) +-- Iteration 5 -- +int(2147483648) +-- Iteration 6 -- +int(-2147483648) diff --git a/ext/standard/tests/general_functions/var_dump_null.phpt b/ext/standard/tests/general_functions/var_dump_null.phpt new file mode 100644 index 0000000000000..e98b74eca930b --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_null.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test var_dump() function with null +--FILE-- + +DONE +--EXPECT-- +NULL +DONE diff --git a/ext/standard/tests/general_functions/var_dump_object.phpt b/ext/standard/tests/general_functions/var_dump_object.phpt new file mode 100644 index 0000000000000..467272574de26 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_object.phpt @@ -0,0 +1,181 @@ +--TEST-- +Test var_dump() function +--FILE-- +value = 50; + $this->public_var2 = 11; + $this->private_var2 = 21; + $this->protected_var2 = "string_2"; + } + + public function foo1() { + echo "foo1() is called\n"; + } + protected function foo2() { + echo "foo2() is called\n"; + } + private function foo3() { + echo "foo3() is called\n"; + } +} + +class no_member_class {} + +/* class with member as object of other class */ +#[AllowDynamicProperties] +class contains_object_class +{ + var $p = 30; + var $class_object1; + public $class_object2; + private $class_object3; + protected $class_object4; + var $no_member_class_object; + + public function func() { + echo "func() is called \n"; + } + + function __construct() { + $this->class_object1 = new object_class(); + $this->class_object2 = new object_class(); + $this->class_object3 = $this->class_object1; + $this->class_object4 = $this->class_object2; + $this->no_member_class_object = new no_member_class(); + $this->class_object5 = $this; //recursive reference + } +} + +$objects = [ + new object_class, + new no_member_class, + new contains_object_class, +]; +check_var_dump($objects); + +?> +--EXPECT-- +*** Testing var_dump() on object variables *** + +-- Iteration 1 -- +object(object_class)#1 (7) { + ["value"]=> + int(50) + ["public_var1"]=> + int(10) + ["private_var1":"object_class":private]=> + int(20) + ["private_var2":"object_class":private]=> + int(21) + ["protected_var1":protected]=> + string(8) "string_1" + ["protected_var2":protected]=> + string(8) "string_2" + ["public_var2"]=> + int(11) +} + +-- Iteration 2 -- +object(no_member_class)#2 (0) { +} + +-- Iteration 3 -- +object(contains_object_class)#3 (7) { + ["p"]=> + int(30) + ["class_object1"]=> + object(object_class)#4 (7) { + ["value"]=> + int(50) + ["public_var1"]=> + int(10) + ["private_var1":"object_class":private]=> + int(20) + ["private_var2":"object_class":private]=> + int(21) + ["protected_var1":protected]=> + string(8) "string_1" + ["protected_var2":protected]=> + string(8) "string_2" + ["public_var2"]=> + int(11) + } + ["class_object2"]=> + object(object_class)#5 (7) { + ["value"]=> + int(50) + ["public_var1"]=> + int(10) + ["private_var1":"object_class":private]=> + int(20) + ["private_var2":"object_class":private]=> + int(21) + ["protected_var1":protected]=> + string(8) "string_1" + ["protected_var2":protected]=> + string(8) "string_2" + ["public_var2"]=> + int(11) + } + ["class_object3":"contains_object_class":private]=> + object(object_class)#4 (7) { + ["value"]=> + int(50) + ["public_var1"]=> + int(10) + ["private_var1":"object_class":private]=> + int(20) + ["private_var2":"object_class":private]=> + int(21) + ["protected_var1":protected]=> + string(8) "string_1" + ["protected_var2":protected]=> + string(8) "string_2" + ["public_var2"]=> + int(11) + } + ["class_object4":protected]=> + object(object_class)#5 (7) { + ["value"]=> + int(50) + ["public_var1"]=> + int(10) + ["private_var1":"object_class":private]=> + int(20) + ["private_var2":"object_class":private]=> + int(21) + ["protected_var1":protected]=> + string(8) "string_1" + ["protected_var2":protected]=> + string(8) "string_2" + ["public_var2"]=> + int(11) + } + ["no_member_class_object"]=> + object(no_member_class)#6 (0) { + } + ["class_object5"]=> + *RECURSION* +} diff --git a/ext/standard/tests/general_functions/var_dump_object_circular.phpt b/ext/standard/tests/general_functions/var_dump_object_circular.phpt new file mode 100644 index 0000000000000..5670346a4bb99 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_object_circular.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test var_dump() function function with circular objects +--FILE-- +obj = $recursion_obj2; +$recursion_obj2->obj = $recursion_obj1; +var_dump($recursion_obj2); + +?> +--EXPECT-- +object(Circular)#2 (1) { + ["obj"]=> + object(Circular)#1 (1) { + ["obj"]=> + *RECURSION* + } +} diff --git a/ext/standard/tests/general_functions/var_dump_resources.phpt b/ext/standard/tests/general_functions/var_dump_resources.phpt new file mode 100644 index 0000000000000..facdc83d42c8d --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_resources.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test var_dump() function with resources +--FILE-- + +--EXPECT-- +resource(1) of type (stream) +resource(3) of type (stream) diff --git a/ext/standard/tests/general_functions/var_dump_strings.phpt b/ext/standard/tests/general_functions/var_dump_strings.phpt new file mode 100644 index 0000000000000..88436318badac --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_strings.phpt @@ -0,0 +1,48 @@ +--TEST-- +Test var_dump() function with strings +--WHITESPACE_SENSITIVE-- +--FILE-- + +--EXPECT-- +-- Iteration 1 -- +string(0) "" +-- Iteration 2 -- +string(1) " " +-- Iteration 3 -- +string(1) "0" +-- Iteration 4 -- +string(2) "\0" +-- Iteration 5 -- +string(1) " " +-- Iteration 6 -- +string(2) "\t" +-- Iteration 7 -- +string(3) "PHP" +-- Iteration 8 -- +string(22) "1234 +5678 + 9100"abcda" diff --git a/ext/standard/tests/general_functions/var_dump_strings_nul_bytes.phpt b/ext/standard/tests/general_functions/var_dump_strings_nul_bytes.phpt new file mode 100644 index 0000000000000000000000000000000000000000..20f06e11cd1f8e29fadba93f346fc03e76940ef3 GIT binary patch literal 663 zcmZuu-)q7!5YBV{ilg{o(O|0X7tZ-GIuK+G=3uZ6i80#Fns#kE>xTdPl6I}SEiZSu zyYJ(^?+BT?k5fYMRHO<%STb8=o49GiGLu{dk%Voad`MLi$W;nFl8OaV=OD8X<~t=) zOvv4M;%biTQS8SU*HG>YzMj>j4V?vS9*We4FAVxMc$7&c5*UIrC@RY+5sdpyI1B?z z4?n1&1}?ZCfkg<6H3uuUtr-dNq*Zd7(Z5UBhh_z8waVHa?=fyvnuqYBSF=27wM}Gm zzVLD?oo=tMBc*5O7nems#d76)dGNLltu}NzwQGfizR1}^@L7YP-kNitnC5`4l%q|@ x1`AoI{q9k}d!+}A2dHoW74i{1)_w}^9f5oO3T&)GMlv#b5jA3wk&28?{0-9k$f^JU literal 0 HcmV?d00001 From ac5e72e2803a192ac4a62c0a078616a856956fb2 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 4 Mar 2025 02:44:27 +0000 Subject: [PATCH 084/503] Add missing clean sections --- ext/standard/tests/file/file_get_contents_basic.phpt | 1 + ext/standard/tests/general_functions/proc_open-mb0.phpt | 4 ++++ ext/standard/tests/general_functions/proc_open-mb1.phpt | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/ext/standard/tests/file/file_get_contents_basic.phpt b/ext/standard/tests/file/file_get_contents_basic.phpt index 96f74c7611917..cf5e4ba6165d8 100644 --- a/ext/standard/tests/file/file_get_contents_basic.phpt +++ b/ext/standard/tests/file/file_get_contents_basic.phpt @@ -29,6 +29,7 @@ echo "\n*** Done ***"; $file_path = __DIR__; include($file_path."/file.inc"); delete_files($file_path, 1); +@unlink($file_path."/file_get_contents_basic1.tmp"); ?> --EXPECT-- *** Testing the basic functionality of the file_get_contents() function *** diff --git a/ext/standard/tests/general_functions/proc_open-mb0.phpt b/ext/standard/tests/general_functions/proc_open-mb0.phpt index 545f087574edb..90ad5533f8240 100644 --- a/ext/standard/tests/general_functions/proc_open-mb0.phpt +++ b/ext/standard/tests/general_functions/proc_open-mb0.phpt @@ -38,6 +38,10 @@ proc_close($p); echo $out; +?> +--CLEAN-- + --EXPECTF-- array(4) { diff --git a/ext/standard/tests/general_functions/proc_open-mb1.phpt b/ext/standard/tests/general_functions/proc_open-mb1.phpt index 057979e604c76..bb220a024804b 100644 --- a/ext/standard/tests/general_functions/proc_open-mb1.phpt +++ b/ext/standard/tests/general_functions/proc_open-mb1.phpt @@ -35,6 +35,10 @@ proc_close($p); echo $out; +?> +--CLEAN-- + --EXPECTF-- array(4) { From 00ebd2d7f25c521a10feae6c8217f6be0825f84d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 13 Mar 2025 13:01:53 +0100 Subject: [PATCH 085/503] Fix flaky connection count in mysqli test Use connection ID instead of count to check whether we're using a persistent connection. This allows the test to be run in parallel with the other tests, but also protects against the possibility that some other service connects to the mysql server. Closes GH-18040 --- ext/mysqli/tests/bug73462.phpt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/ext/mysqli/tests/bug73462.phpt b/ext/mysqli/tests/bug73462.phpt index c4d68ca4f5935..318b8dd24b34d 100644 --- a/ext/mysqli/tests/bug73462.phpt +++ b/ext/mysqli/tests/bug73462.phpt @@ -5,13 +5,6 @@ mysqli --SKIPIF-- --FILE-- query("SHOW STATUS LIKE 'Connections'"); + $result = $mysql_1->query("SELECT CONNECTION_ID()"); $c1 = $result->fetch_row(); $result->free(); $mysql_1->close(); @@ -35,7 +28,7 @@ if (gethostname() == "php-ci-ppc64be") { /* Re-use persistent connection */ $mysql_3 = new mysqli('p:'.$host, $user, $passwd, $db, $port); $error = mysqli_connect_errno(); - $result = $mysql_3->query("SHOW STATUS LIKE 'Connections'"); + $result = $mysql_3->query("SELECT CONNECTION_ID()"); $c3 = $result->fetch_row(); $result->free(); $mysql_3->close(); From 54f93f127ee93e43233c1620e19a20414283f94d Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Thu, 13 Mar 2025 13:14:37 -0400 Subject: [PATCH 086/503] [skip ci] Fix release date of 8.3.19 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 39ee4c46becda..defd19e93f4ee 100644 --- a/NEWS +++ b/NEWS @@ -23,7 +23,7 @@ PHP NEWS - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) -13 Feb 2025, PHP 8.3.19 +13 Mar 2025, PHP 8.3.19 - BCMath: . Fixed bug GH-17398 (bcmul memory leak). (SakiTakamachi) From c62523666c9fef743d34f2adc1d6c7de479e4870 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Thu, 13 Mar 2025 13:45:08 -0400 Subject: [PATCH 087/503] [skip ci] Fix invalid release date of 8.1.1 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 67f6b8f728be7..f34fc5c90e5de 100644 --- a/NEWS +++ b/NEWS @@ -1590,7 +1590,7 @@ PHP NEWS . Fixed bug GH-7815 (php_uname doesn't recognise latest Windows versions). (David Warner) -02 Dec 2021, PHP 8.1.1 +16 Dec 2021, PHP 8.1.1 - IMAP: . Fixed bug #81649 (imap_(un)delete accept sequences, not single numbers). From 200342145410e71654e2327e80febfd7d9c93483 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Thu, 13 Mar 2025 13:48:38 -0400 Subject: [PATCH 088/503] [skip ci] Fix release dates on NEWS --- NEWS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index defd19e93f4ee..4fa4fee3d849e 100644 --- a/NEWS +++ b/NEWS @@ -199,7 +199,7 @@ PHP NEWS . Fixed bug GH-17139 (Fix zip_entry_name() crash on invalid entry). (nielsdos) -02 Jan 2025, PHP 8.3.16 +16 Jan 2025, PHP 8.3.16 - Core: . Fixed bug GH-17106 (ZEND_MATCH_ERROR misoptimization). (ilutov) @@ -398,7 +398,7 @@ PHP NEWS - Windows: . Fixed bug GH-16849 (Error dialog causes process to hang). (cmb) -07 Nov 2024, PHP 8.3.14 +21 Nov 2024, PHP 8.3.14 - CLI: . Fixed bug GH-16373 (Shebang is not skipped for router script in cli-server @@ -919,7 +919,7 @@ PHP NEWS . Fixed bug GH-14834 (Error installing PHP when --with-pear is used). (nielsdos) -20 Jun 2024, PHP 8.3.9 +04 Jul 2024, PHP 8.3.9 - Core: . Fixed bug GH-14315 (Incompatible pointer type warnings). (Peter Kokot) @@ -1151,7 +1151,7 @@ PHP NEWS - Treewide: . Fix gcc-14 Wcalloc-transposed-args warnings. (Cristian Rodríguez) -28 Mar 2024, PHP 8.3.5 +11 Apr 2024, PHP 8.3.6 - Core: . Fixed GH-13569 (GC buffer unnecessarily grows up to GC_MAX_BUF_SIZE when @@ -1420,7 +1420,7 @@ PHP NEWS . Fixed bug GH-12980 (tidynode.props.attribute is missing "Boolean Attributes" and empty attributes). (nielsdos) -07 Dec 2023, PHP 8.3.1 +21 Dec 2023, PHP 8.3.1 - Core: . Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within From a3aaedc76c5ede48bd49c93f08eb7e828133a425 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Thu, 13 Mar 2025 13:50:06 -0400 Subject: [PATCH 089/503] [skip ci] Fix release dates on NEWS --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index f2bd84c21c4c2..7f7a616bc1c26 100644 --- a/NEWS +++ b/NEWS @@ -162,7 +162,7 @@ PHP NEWS . Fix memory leak when encoding check fails. (nielsdos) . Fix zlib support for large files. (nielsdos) -30 Jan 2025, PHP 8.4.4 +13 Feb 2025, PHP 8.4.4 - Core: . Fixed bug GH-17234 (Numeric parent hook call fails with assertion). @@ -281,7 +281,7 @@ PHP NEWS . Fixed bug GH-17139 (Fix zip_entry_name() crash on invalid entry). (nielsdos) -02 Jan 2025, PHP 8.4.3 +16 Jan 2025, PHP 8.4.3 - BcMath: . Fixed bug GH-17049 (Correctly compare 0 and -0). (Saki Takamachi) @@ -410,7 +410,7 @@ PHP NEWS - XML: . Fixed bug GH-1718 (unreachable program point in zend_hash). (nielsdos) -05 Dec 2024, PHP 8.4.2 +19 Dec 2024, PHP 8.4.2 - BcMath: . Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros). From 27affd8da173db7f7db5535c4caaf55d2986f925 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 12 Mar 2025 19:39:58 +0100 Subject: [PATCH 090/503] Fix GH-18018: RC1 data returned from offsetGet causes UAF in ArrayObject We should first check truthiness and only after that destroy the value. Closes GH-18034. --- NEWS | 4 ++++ ext/spl/spl_array.c | 6 ++++-- ext/spl/tests/gh18018.phpt | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/gh18018.phpt diff --git a/NEWS b/NEWS index 4fa4fee3d849e..58de3a7ed3cd8 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) +- SPL: + . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in + ArrayObject). (nielsdos) + - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index bd03a8aae0189..8d4541797a1c5 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -641,12 +641,14 @@ static bool spl_array_has_dimension_ex(bool check_inherited, zend_object *object } } + /* empty() check the value is not falsy, isset() only check it is not null */ + bool result = check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; + if (value == &rv) { zval_ptr_dtor(&rv); } - /* empty() check the value is not falsy, isset() only check it is not null */ - return check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; + return result; } /* }}} */ static int spl_array_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ diff --git a/ext/spl/tests/gh18018.phpt b/ext/spl/tests/gh18018.phpt new file mode 100644 index 0000000000000..06fa7fc3d0e55 --- /dev/null +++ b/ext/spl/tests/gh18018.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject) +--FILE-- + 1]; + +$object = new Crap($values); + +var_dump(empty($object['qux'])); +?> +--EXPECT-- +bool(false) From 3c17d3fc054e3b964b77c7a12a632201bd53b027 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Mar 2025 19:11:53 +0100 Subject: [PATCH 091/503] [ci skip] Fix NEWS order --- NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 4cb6bbb091203..43f43d7757fe3 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,10 @@ PHP NEWS . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) . Fix weird unpack behaviour in DOM. (nielsdos) +- GD: + . Fixed bug GH-17984 (calls with arguments as array with references). + (David Carlier) + - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) @@ -40,10 +44,6 @@ PHP NEWS - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) -- GD: - . Fixed bug GH-17984 (calls with arguments as array with references). - (David Carlier) - - SPL: . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) From 70c2ebb69807d517fa38487e690462454c83f1ec Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 13 Mar 2025 22:24:49 +0100 Subject: [PATCH 092/503] Fix typo in GHSA-hgf5-96fm-v528 NEWS entry --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f34fc5c90e5de..29400e6ef5b5c 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ PHP NEWS when requesting a redirected resource). (CVE-2025-1219) (timwolla) - Streams: - . Fixed GHSA-hgf54-96fm-v528 (Stream HTTP wrapper header check might omit + . Fixed GHSA-hgf5-96fm-v528 (Stream HTTP wrapper header check might omit basic auth header). (CVE-2025-1736) (Jakub Zelenka) . Fixed GHSA-52jp-hrpf-2jff (Stream HTTP wrapper truncate redirect location to 1024 bytes). (CVE-2025-1861) (Jakub Zelenka) From a7d2703246cb4acdcb48ecb3682386a102702c43 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Mar 2025 21:18:35 +0100 Subject: [PATCH 093/503] Correct check for maximum string length in JIT helpers This is a bit of a theoretical issue, but the maximum string length is actually ZSTR_MAX_LEN instead of SIZE_MAX. The resulting check is a bit slower but should still be relatively cheap. Closes GH-18049. --- ext/opcache/jit/zend_jit_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index a79f2b5173d53..26e368dce6617 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1636,7 +1636,7 @@ static void ZEND_FASTCALL zend_jit_fast_assign_concat_helper(zval *op1, zval *op zend_string *result_str; uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(Z_STR_P(op1), Z_STR_P(op2)); - if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) { + if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) { zend_throw_error(NULL, "String size overflow"); return; } @@ -1672,7 +1672,7 @@ static void ZEND_FASTCALL zend_jit_fast_concat_helper(zval *result, zval *op1, z zend_string *result_str; uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(Z_STR_P(op1), Z_STR_P(op2)); - if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) { + if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) { zend_throw_error(NULL, "String size overflow"); return; } @@ -1696,7 +1696,7 @@ static void ZEND_FASTCALL zend_jit_fast_concat_tmp_helper(zval *result, zval *op zend_string *result_str; uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(Z_STR_P(op1), Z_STR_P(op2)); - if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) { + if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) { zend_throw_error(NULL, "String size overflow"); return; } From 413938143b31405817abbdf0f8effb7c09ed0862 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Mar 2025 21:05:33 +0100 Subject: [PATCH 094/503] Fix GH-18037: SEGV Zend/zend_execute.c A frameless icall with 3 arguments is a special case because it uses OP_DATA, but this was not added to the list, so the opline pointed to the wrong address resulting in UBSAN report or crash. Closes GH-18048. --- NEWS | 1 + ext/opcache/jit/zend_jit_ir.c | 1 + ext/opcache/tests/jit/gh18037.phpt | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 ext/opcache/tests/jit/gh18037.phpt diff --git a/NEWS b/NEWS index 309bf290f28f8..72b890d29855d 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,7 @@ PHP NEWS . Fixed bug GH-15834 (Segfault with hook "simple get" cache slot and minimal JIT). (nielsdos) . Fixed bug GH-17966 (Symfony JIT 1205 assertion failure). (nielsdos) + . Fixed bug GH-18037 (SEGV Zend/zend_execute.c). (nielsdos) - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 32c58f24c7cd2..7ff6522ba2c4a 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -4209,6 +4209,7 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_STATIC_PROP_REF: case ZEND_ASSIGN_OBJ_REF: + case ZEND_FRAMELESS_ICALL_3: zend_jit_set_last_valid_opline(jit, opline + 2); break; default: diff --git a/ext/opcache/tests/jit/gh18037.phpt b/ext/opcache/tests/jit/gh18037.phpt new file mode 100644 index 0000000000000..26de60228e8cb --- /dev/null +++ b/ext/opcache/tests/jit/gh18037.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-18037 (SEGV Zend/zend_execute.c) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1201 +--FILE-- +matches(); +} + +test_helper(); +?> +--EXPECTF-- +Warning: Undefined array key 0 in %s on line %d + +Fatal error: Uncaught Error: Call to a member function matches() on array in %s:%d +Stack trace: +#0 %s(%d): test_helper() +#1 {main} + thrown in %s on line %d From 4e4f1729ddf1131895b678cd7f12354a4a5ce0c0 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Fri, 14 Mar 2025 08:53:48 +0900 Subject: [PATCH 095/503] ext/bcmath: Simplify `bc_divide()` code (#17987) Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- NEWS | 3 + ext/bcmath/libbcmath/src/convert.h | 34 +++- ext/bcmath/libbcmath/src/div.c | 256 +++++++++++------------------ ext/bcmath/libbcmath/src/private.h | 9 + 4 files changed, 141 insertions(+), 161 deletions(-) diff --git a/NEWS b/NEWS index 2268ebedc7b45..f941ce90e47f1 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.5.0alpha1 +- BCMath: + . Simplify `bc_divide()` code. (SakiTakamachi) + - CLI: . Add --ini=diff to print INI settings changed from the builtin default. (timwolla) diff --git a/ext/bcmath/libbcmath/src/convert.h b/ext/bcmath/libbcmath/src/convert.h index 6ddd447c8048e..e278ae5fef1aa 100644 --- a/ext/bcmath/libbcmath/src/convert.h +++ b/ext/bcmath/libbcmath/src/convert.h @@ -34,11 +34,11 @@ static inline BC_VECTOR bc_partial_convert_to_vector(const char *n, size_t len) } BC_VECTOR num = 0; - BC_VECTOR base = 1; + BC_VECTOR digit_base_value = 1; for (size_t i = 0; i < len; i++) { - num += *n * base; - base *= BASE; + num += *n * digit_base_value; + digit_base_value *= BASE; n--; } @@ -57,4 +57,32 @@ static inline void bc_convert_to_vector(BC_VECTOR *n_vector, const char *nend, s } } +static inline void bc_convert_to_vector_with_zero_pad(BC_VECTOR *n_vector, const char *nend, size_t nlen, size_t zeros) +{ + while (zeros >= BC_VECTOR_SIZE) { + *n_vector = 0; + n_vector++; + zeros -= BC_VECTOR_SIZE; + } + + if (zeros > 0) { + *n_vector = 0; + BC_VECTOR digit_base_value = BC_POW_10_LUT[zeros]; + size_t len_to_write = MIN(BC_VECTOR_SIZE - zeros, nlen); + for (size_t i = 0; i < len_to_write; i++) { + *n_vector += *nend * digit_base_value; + digit_base_value *= BASE; + nend--; + } + n_vector++; + nlen -= len_to_write; + } + + if (nlen == 0) { + return; + } + + bc_convert_to_vector(n_vector, nend, nlen); +} + #endif diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index ce9ae1e1dd792..cda452569dedc 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -37,10 +37,6 @@ #include #include "zend_alloc.h" -static const BC_VECTOR POW_10_LUT[9] = { - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 -}; - /* * This function should be used when the divisor is not split into multiple chunks, i.e. when the size of the array is one. * This is because the algorithm can be simplified. @@ -51,7 +47,7 @@ static inline void bc_fast_div( { size_t numerator_top_index = numerator_arr_size - 1; size_t quot_top_index = quot_arr_size - 1; - for (size_t i = 0; i < quot_arr_size - 1; i++) { + for (size_t i = 0; i < quot_top_index; i++) { if (numerator_vectors[numerator_top_index - i] < divisor_vector) { quot_vectors[quot_top_index - i] = 0; /* numerator_vectors[numerator_top_index - i] < divisor_vector, so there will be no overflow. */ @@ -174,8 +170,8 @@ static inline void bc_standard_div( divisor_top_digits = BC_VECTOR_SIZE; } - size_t high_part_shift = POW_10_LUT[BC_VECTOR_SIZE - divisor_top_digits + 1]; - size_t low_part_shift = POW_10_LUT[divisor_top_digits - 1]; + size_t high_part_shift = BC_POW_10_LUT[BC_VECTOR_SIZE - divisor_top_digits + 1]; + size_t low_part_shift = BC_POW_10_LUT[divisor_top_digits - 1]; BC_VECTOR divisor_high_part = divisor_vectors[divisor_top_index] * high_part_shift + divisor_vectors[divisor_top_index - 1] / low_part_shift; for (size_t i = 0; i < quot_arr_size; i++) { BC_VECTOR numerator_high_part = numerator_vectors[numerator_top_index - i] * high_part_shift + numerator_vectors[numerator_top_index - i - 1] / low_part_shift; @@ -255,58 +251,39 @@ static inline void bc_standard_div( } static void bc_do_div( - const char *numerator, size_t numerator_readable_len, size_t numerator_bottom_extension, - const char *divisor, size_t divisor_len, bc_num *quot, size_t quot_len + const char *numerator, size_t numerator_size, size_t numerator_readable_size, + const char *divisor, size_t divisor_size, + bc_num *quot, size_t quot_size ) { - size_t divisor_arr_size = (divisor_len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t numerator_arr_size = (numerator_readable_len + numerator_bottom_extension + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t numerator_arr_size = (numerator_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t divisor_arr_size = (divisor_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1; - size_t quot_real_arr_size = MIN(quot_arr_size, (quot_len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); + size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); BC_VECTOR *numerator_vectors = safe_emalloc(numerator_arr_size + divisor_arr_size + quot_arr_size, sizeof(BC_VECTOR), 0); BC_VECTOR *divisor_vectors = numerator_vectors + numerator_arr_size; BC_VECTOR *quot_vectors = divisor_vectors + divisor_arr_size; - /* Fill with zeros and convert as many vector elements as needed */ - size_t numerator_vector_count = 0; - while (numerator_bottom_extension >= BC_VECTOR_SIZE) { - numerator_vectors[numerator_vector_count] = 0; - numerator_bottom_extension -= BC_VECTOR_SIZE; - numerator_vector_count++; - } - - size_t numerator_bottom_read_len = BC_VECTOR_SIZE - numerator_bottom_extension; - - size_t base; - size_t numerator_read = 0; - if (numerator_bottom_read_len < BC_VECTOR_SIZE) { - numerator_read = MIN(numerator_bottom_read_len, numerator_readable_len); - base = POW_10_LUT[numerator_bottom_extension]; - numerator_vectors[numerator_vector_count] = 0; - for (size_t i = 0; i < numerator_read; i++) { - numerator_vectors[numerator_vector_count] += *numerator * base; - base *= BASE; - numerator--; - } - numerator_vector_count++; - } + size_t numerator_extension = numerator_size > numerator_readable_size ? numerator_size - numerator_readable_size : 0; /* Bulk convert numerator and divisor to vectors */ - if (numerator_readable_len > numerator_read) { - bc_convert_to_vector(numerator_vectors + numerator_vector_count, numerator, numerator_readable_len - numerator_read); - } - bc_convert_to_vector(divisor_vectors, divisor, divisor_len); + size_t numerator_use_size = numerator_size - numerator_extension; + const char *numerator_end = numerator + numerator_use_size - 1; + bc_convert_to_vector_with_zero_pad(numerator_vectors, numerator_end, numerator_use_size, numerator_extension); + + const char *divisor_end = divisor + divisor_size - 1; + bc_convert_to_vector(divisor_vectors, divisor_end, divisor_size); /* Do the division */ if (divisor_arr_size == 1) { bc_fast_div(numerator_vectors, numerator_arr_size, divisor_vectors[0], quot_vectors, quot_arr_size); } else { - bc_standard_div(numerator_vectors, numerator_arr_size, divisor_vectors, divisor_arr_size, divisor_len, quot_vectors, quot_arr_size); + bc_standard_div(numerator_vectors, numerator_arr_size, divisor_vectors, divisor_arr_size, divisor_size, quot_vectors, quot_arr_size); } /* Convert to bc_num */ char *qptr = (*quot)->n_value; - char *qend = qptr + quot_len - 1; + char *qend = qptr + (*quot)->n_len + (*quot)->n_scale - 1; size_t i; for (i = 0; i < quot_real_arr_size - 1; i++) { @@ -328,6 +305,38 @@ static void bc_do_div( efree(numerator_vectors); } +static inline void bc_divide_by_one(bc_num numerator, bc_num *quot, size_t quot_scale) +{ + quot_scale = MIN(numerator->n_scale, quot_scale); + *quot = bc_new_num_nonzeroed(numerator->n_len, quot_scale); + char *qptr = (*quot)->n_value; + memcpy(qptr, numerator->n_value, numerator->n_len + quot_scale); +} + +static inline void bc_divide_by_pow_10( + const char *numeratorptr, size_t numerator_readable_size, bc_num *quot, size_t quot_size, size_t quot_scale) +{ + char *qptr = (*quot)->n_value; + for (size_t i = quot_size; i <= quot_scale; i++) { + *qptr++ = 0; + } + + size_t numerator_use_size = quot_size > numerator_readable_size ? numerator_readable_size : quot_size; + memcpy(qptr, numeratorptr, numerator_use_size); + qptr += numerator_use_size; + + if (numerator_use_size < (*quot)->n_len) { + /* e.g. 12.3 / 0.01 <=> 1230 */ + for (size_t i = numerator_use_size; i < (*quot)->n_len; i++) { + *qptr++ = 0; + } + (*quot)->n_scale = 0; + } else { + char *qend = (*quot)->n_value + (*quot)->n_len + (*quot)->n_scale; + (*quot)->n_scale -= qend - qptr; + } +} + bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) { /* divide by zero */ @@ -336,166 +345,97 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) } bc_free_num(quot); + size_t quot_scale = scale; /* If numerator is zero, the quotient is always zero. */ if (bc_is_zero(numerator)) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + goto quot_zero; } /* If divisor is 1 / -1, the quotient's n_value is equal to numerator's n_value. */ if (_bc_do_compare(divisor, BCG(_one_), divisor->n_scale, false) == BCMATH_EQUAL) { - size_t quot_scale = MIN(numerator->n_scale, scale); - *quot = bc_new_num_nonzeroed(numerator->n_len, quot_scale); - char *qptr = (*quot)->n_value; - memcpy(qptr, numerator->n_value, numerator->n_len + quot_scale); + bc_divide_by_one(numerator, quot, quot_scale); (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; - _bc_rm_leading_zeros(*quot); return true; } char *numeratorptr = numerator->n_value; - char *numeratorend = numeratorptr + numerator->n_len + numerator->n_scale - 1; - size_t numerator_len = numerator->n_len; - size_t numerator_scale = numerator->n_scale; + size_t numerator_size = numerator->n_len + quot_scale + divisor->n_scale; char *divisorptr = divisor->n_value; - char *divisorend = divisorptr + divisor->n_len + divisor->n_scale - 1; - size_t divisor_len = divisor->n_len; - size_t divisor_scale = divisor->n_scale; - size_t divisor_int_right_zeros = 0; - - /* remove divisor trailing zeros */ - while (*divisorend == 0 && divisor_scale > 0) { - divisorend--; - divisor_scale--; - } - while (*divisorend == 0) { - divisorend--; - divisor_int_right_zeros++; - } + size_t divisor_size = divisor->n_len + divisor->n_scale; - if (*numeratorptr == 0 && numerator_len == 1) { + /* check and remove numerator leading zeros */ + size_t numerator_leading_zeros = 0; + while (*numeratorptr == 0) { numeratorptr++; - numerator_len = 0; + numerator_leading_zeros++; } - - size_t numerator_top_extension = 0; - size_t numerator_bottom_extension = 0; - if (divisor_scale > 0) { - /* - * e.g. divisor_scale = 4 - * divisor = .0002, to be 2 or divisor = 200.001, to be 200001 - * numerator = .03, to be 300 or numerator = .000003, to be .03 - * numerator may become longer than the original data length due to the addition of - * trailing zeros in the integer part. - */ - numerator_len += divisor_scale; - numerator_bottom_extension = numerator_scale < divisor_scale ? divisor_scale - numerator_scale : 0; - numerator_scale = numerator_scale > divisor_scale ? numerator_scale - divisor_scale : 0; - divisor_len += divisor_scale; - divisor_scale = 0; - } else if (divisor_int_right_zeros > 0) { - /* - * e.g. divisor_int_right_zeros = 4 - * divisor = 2000, to be 2 - * numerator = 30, to be .03 or numerator = 30000, to be 30 - * Also, numerator may become longer than the original data length due to the addition of - * leading zeros in the fractional part. - */ - numerator_top_extension = numerator_len < divisor_int_right_zeros ? divisor_int_right_zeros - numerator_len : 0; - numerator_len = numerator_len > divisor_int_right_zeros ? numerator_len - divisor_int_right_zeros : 0; - numerator_scale += divisor_int_right_zeros; - divisor_len -= divisor_int_right_zeros; - divisor_scale = 0; + if (numerator_size > numerator_leading_zeros) { + numerator_size -= numerator_leading_zeros; + } else { + goto quot_zero; } - /* remove numerator leading zeros */ - while (*numeratorptr == 0 && numerator_len > 0) { - numeratorptr++; - numerator_len--; - } - /* remove divisor leading zeros */ + /* check and remove divisor leading zeros */ while (*divisorptr == 0) { divisorptr++; - divisor_len--; + divisor_size--; } - /* Considering the scale specification, the quotient is always 0 if this condition is met */ - if (divisor_len > numerator_len + scale) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + if (divisor_size > numerator_size) { + goto quot_zero; } - /* Length of numerator data that can be read */ - size_t numerator_readable_len = numeratorend - numeratorptr + 1; - - /* set scale to numerator */ - if (numerator_scale > scale) { - size_t scale_diff = numerator_scale - scale; - if (numerator_bottom_extension > scale_diff) { - numerator_bottom_extension -= scale_diff; - } else { - numerator_bottom_extension = 0; - if (EXPECTED(numerator_readable_len > scale_diff)) { - numerator_readable_len -= scale_diff; - numeratorend -= scale_diff; - } else { - numerator_readable_len = 0; - numeratorend = numeratorptr; - } + /* check and remove divisor trailing zeros. The divisor is not 0, so leave only one digit */ + size_t divisor_trailing_zeros = 0; + for (size_t i = divisor_size - 1; i > 0; i--) { + if (divisorptr[i] != 0) { + break; } - numerator_top_extension = MIN(numerator_top_extension, scale); + divisor_trailing_zeros++; + } + divisor_size -= divisor_trailing_zeros; + + if (numerator_size > divisor_trailing_zeros) { + numerator_size -= divisor_trailing_zeros; } else { - numerator_bottom_extension += scale - numerator_scale; + goto quot_zero; } - numerator_scale = scale; - if (divisor_len > numerator_readable_len + numerator_bottom_extension) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + size_t quot_size = numerator_size - divisor_size + 1; /* numerator_size >= divisor_size */ + if (quot_size > quot_scale) { + *quot = bc_new_num_nonzeroed(quot_size - quot_scale, quot_scale); + } else { + *quot = bc_new_num_nonzeroed(1, quot_scale); /* 1 is for 0 */ } - /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ - if (divisor_len == 1 && *divisorptr == 1) { - if (numerator_len == 0) { - numerator_len = 1; - numerator_top_extension++; - } - size_t quot_scale = numerator_scale > numerator_bottom_extension ? numerator_scale - numerator_bottom_extension : 0; - numerator_bottom_extension = numerator_scale < numerator_bottom_extension ? numerator_bottom_extension - numerator_scale : 0; + /* Size that can be read from numeratorptr */ + size_t numerator_readable_size = numerator->n_len + numerator->n_scale - numerator_leading_zeros; - *quot = bc_new_num_nonzeroed(numerator_len, quot_scale); - char *qptr = (*quot)->n_value; - for (size_t i = 0; i < numerator_top_extension; i++) { - *qptr++ = 0; - } - memcpy(qptr, numeratorptr, numerator_readable_len); - qptr += numerator_readable_len; - for (size_t i = 0; i < numerator_bottom_extension; i++) { - *qptr++ = 0; - } + /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ + if (divisor_size == 1 && *divisorptr == 1) { + bc_divide_by_pow_10(numeratorptr, numerator_readable_size, quot, quot_size, quot_scale); (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; return true; } - size_t quot_full_len; - if (divisor_len > numerator_len) { - *quot = bc_new_num_nonzeroed(1, scale); - quot_full_len = 1 + scale; - } else { - *quot = bc_new_num_nonzeroed(numerator_len - divisor_len + 1, scale); - quot_full_len = numerator_len - divisor_len + 1 + scale; - } - /* do divide */ - bc_do_div(numeratorend, numerator_readable_len, numerator_bottom_extension, divisorend, divisor_len, quot, quot_full_len); + bc_do_div( + numeratorptr, numerator_size, numerator_readable_size, + divisorptr, divisor_size, + quot, quot_size + ); + _bc_rm_leading_zeros(*quot); if (bc_is_zero(*quot)) { (*quot)->n_sign = PLUS; } else { (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; } + return true; +quot_zero: + *quot = bc_copy_num(BCG(_zero_)); return true; } diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 5c0087901a4a2..1a911442dc9a1 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -35,6 +35,9 @@ #include #include "zend_portability.h" +#ifndef _BCMATH_PRIV_H_ +#define _BCMATH_PRIV_H_ + /* This will be 0x01010101 for 32-bit and 0x0101010101010101 for 64-bit */ #define SWAR_ONES (~((size_t) 0) / 0xFF) /* This repeats a byte `x` into an entire 32/64-bit word. @@ -67,9 +70,15 @@ */ #define BC_VECTOR_NO_OVERFLOW_ADD_COUNT (~((BC_VECTOR) 0) / (BC_VECTOR_BOUNDARY_NUM * BC_VECTOR_BOUNDARY_NUM)) +static const BC_VECTOR BC_POW_10_LUT[9] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 +}; + /* routines */ bcmath_compare_result _bc_do_compare (bc_num n1, bc_num n2, size_t scale, bool use_sign); bc_num _bc_do_add (bc_num n1, bc_num n2); bc_num _bc_do_sub (bc_num n1, bc_num n2); void _bc_rm_leading_zeros (bc_num num); + +#endif From 7c9872e255b33a4d455c18153f1967b87654f443 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 09:00:00 +0900 Subject: [PATCH 096/503] Fixed pointer subtraction for scale (#17986) Closes #17986 --- NEWS | 3 +++ ext/bcmath/libbcmath/src/str2num.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 72b890d29855d..7bcfc484d7302 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.6 +- BCMath: + . Fixed pointer subtraction for scale. (SakiTakamachi) + - Core: . Fixed property hook backing value access in multi-level inheritance. (ilutov) diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c index 79c1d4216fe7b..bd9a44a240503 100644 --- a/ext/bcmath/libbcmath/src/str2num.c +++ b/ext/bcmath/libbcmath/src/str2num.c @@ -180,7 +180,7 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz */ if (str_scale > 0) { const char *fractional_new_end = bc_skip_zero_reverse(fractional_end, fractional_ptr); - str_scale -= fractional_new_end - fractional_end; + str_scale -= fractional_end - fractional_new_end; /* fractional_end >= fractional_new_end */ } } } else { From 32547f11271ebd9a4f29202179e1cc5e12c333a8 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Fri, 14 Mar 2025 17:52:50 +0900 Subject: [PATCH 097/503] ext/bcmath: If the result is `0`, `n_scale` is set to `0`. (#18056) --- NEWS | 1 + ext/bcmath/bcmath.c | 9 +++++---- ext/bcmath/libbcmath/src/bcmath.h | 2 +- ext/bcmath/libbcmath/src/div.c | 1 + ext/bcmath/libbcmath/src/divmod.c | 1 + ext/bcmath/libbcmath/src/recmul.c | 1 + ext/bcmath/libbcmath/src/round.c | 24 +++++++++++++++--------- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index f941ce90e47f1..bd7c6b3a26ae0 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ PHP NEWS - BCMath: . Simplify `bc_divide()` code. (SakiTakamachi) + . If the result is 0, n_scale is set to 0. (SakiTakamachi) - CLI: . Add --ini=diff to print INI settings changed from the builtin default. diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 233045bd7cd7e..962f839ba83f4 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -807,8 +807,8 @@ PHP_FUNCTION(bcround) goto cleanup; } - bc_round(num, precision, mode, &result); - RETVAL_NEW_STR(bc_num2str_ex(result, result->n_scale)); + size_t scale = bc_round(num, precision, mode, &result); + RETVAL_NEW_STR(bc_num2str_ex(result, scale)); cleanup: { bc_free_num(&num); @@ -1799,9 +1799,10 @@ PHP_METHOD(BcMath_Number, round) bcmath_number_obj_t *intern = get_bcmath_number_from_zval(ZEND_THIS); bc_num ret = NULL; - bc_round(intern->num, precision, rounding_mode, &ret); + size_t scale = bc_round(intern->num, precision, rounding_mode, &ret); + bc_rm_trailing_zeros(ret); - bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, ret->n_scale); + bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, scale); RETURN_OBJ(&new_intern->std); } diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index f7e14019bd336..1f05ad51f7f26 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -157,7 +157,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, size_t scale) bc_num bc_floor_or_ceil(bc_num num, bool is_floor); -void bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result); +size_t bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result); typedef enum { OK, diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index cda452569dedc..ec7619fb77090 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -430,6 +430,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) _bc_rm_leading_zeros(*quot); if (bc_is_zero(*quot)) { (*quot)->n_sign = PLUS; + (*quot)->n_scale = 0; } else { (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; } diff --git a/ext/bcmath/libbcmath/src/divmod.c b/ext/bcmath/libbcmath/src/divmod.c index 294a281b2e687..477ec30e916ea 100644 --- a/ext/bcmath/libbcmath/src/divmod.c +++ b/ext/bcmath/libbcmath/src/divmod.c @@ -74,6 +74,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, size_t scale (*rem)->n_scale = MIN(scale, (*rem)->n_scale); if (bc_is_zero(*rem)) { (*rem)->n_sign = PLUS; + (*rem)->n_scale = 0; } return true; diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index b92a1045ac3b5..de06a4ca037ec 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -264,6 +264,7 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale) _bc_rm_leading_zeros(prod); if (bc_is_zero(prod)) { prod->n_sign = PLUS; + prod->n_scale = 0; } return prod; } diff --git a/ext/bcmath/libbcmath/src/round.c b/ext/bcmath/libbcmath/src/round.c index ac3c7c41a315e..44df6036cbe3b 100644 --- a/ext/bcmath/libbcmath/src/round.c +++ b/ext/bcmath/libbcmath/src/round.c @@ -18,7 +18,8 @@ #include "private.h" #include -void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) +/* Returns the scale of the value after rounding. */ +size_t bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) { /* clear result */ bc_free_num(result); @@ -43,19 +44,19 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) case PHP_ROUND_HALF_ODD: case PHP_ROUND_TOWARD_ZERO: *result = bc_copy_num(BCG(_zero_)); - return; + return 0; case PHP_ROUND_CEILING: if (num->n_sign == MINUS) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } break; case PHP_ROUND_FLOOR: if (num->n_sign == PLUS) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } break; @@ -67,7 +68,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) if (bc_is_zero(num)) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } /* If precision is -3, it becomes 1000. */ @@ -78,7 +79,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) } (*result)->n_value[0] = 1; (*result)->n_sign = num->n_sign; - return; + return 0; } /* Just like bcadd('1', '1', 4) becomes '2.0000', it pads with zeros at the end if necessary. */ @@ -90,7 +91,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) (*result)->n_sign = num->n_sign; memcpy((*result)->n_value, num->n_value, num->n_len + num->n_scale); } - return; + return precision; } /* @@ -222,7 +223,12 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) } check_zero: - if (bc_is_zero(*result)) { - (*result)->n_sign = PLUS; + { + size_t scale = (*result)->n_scale; + if (bc_is_zero(*result)) { + (*result)->n_sign = PLUS; + (*result)->n_scale = 0; + } + return scale; } } From 1c182674b09b88cb3ca954740504ba57aa1826ad Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 3 Mar 2025 13:12:21 +0100 Subject: [PATCH 098/503] Destroy temporary module classes in reverse order We destroy classes of dl()'ed modules in clean_module_classes(), during shutdown. Child classes of a module use structures of the parent class (such as inherited properties), which are destroyed earlier, so we have a use-after-free when destroying a child class. Here I destroy classes in reverse order, as it is done in zend_shutdown() for persistent classes. Fixes GH-17961 Fixes GH-15367 --- NEWS | 6 ++++ Zend/zend_API.c | 23 ++++++-------- ext/dl_test/dl_test.c | 12 ++++++++ ext/dl_test/dl_test.stub.php | 12 ++++++++ ext/dl_test/dl_test_arginfo.h | 58 ++++++++++++++++++++++++++++++++++- 5 files changed, 97 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index a6e51761301b8..3f4b5aa2bc83a 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.20 +- Core: + . Fixed bug GH-17961 (use-after-free during dl()'ed module class destruction). + (Arnaud) + . Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown). + (Arnaud) + - DOM: . Fix weird unpack behaviour in DOM. (nielsdos) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 13c640a64dd51..47de6e7897546 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -22,6 +22,7 @@ #include "zend.h" #include "zend_execute.h" #include "zend_API.h" +#include "zend_hash.h" #include "zend_modules.h" #include "zend_extensions.h" #include "zend_constants.h" @@ -3111,21 +3112,17 @@ ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */ } /* }}} */ -static int clean_module_class(zval *el, void *arg) /* {{{ */ -{ - zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el); - int module_number = *(int *)arg; - if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) { - return ZEND_HASH_APPLY_REMOVE; - } else { - return ZEND_HASH_APPLY_KEEP; - } -} -/* }}} */ - static void clean_module_classes(int module_number) /* {{{ */ { - zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number); + /* Child classes may reuse structures from parent classes, so destroy in reverse order. */ + Bucket *bucket; + ZEND_HASH_REVERSE_FOREACH_BUCKET(EG(class_table), bucket) { + zend_class_entry *ce = Z_CE(bucket->val); + if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) { + zend_hash_del_bucket(EG(class_table), bucket); + } + } ZEND_HASH_FOREACH_END(); + } /* }}} */ diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 1121a96b9df8d..1176a874d6027 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -92,10 +92,22 @@ PHP_METHOD(DlTest, test) RETURN_STR(retval); } +PHP_METHOD(DlTestSuperClass, test) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_NULL(); +} + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(dl_test) { + zend_class_entry *ce; + register_class_DlTest(); + ce = register_class_DlTestSuperClass(); + register_class_DlTestSubClass(ce); + register_class_DlTestAliasedClass(); /* Test backwards compatibility */ if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php index cd8b3916bae2e..c2d8ff577780f 100644 --- a/ext/dl_test/dl_test.stub.php +++ b/ext/dl_test/dl_test.stub.php @@ -12,3 +12,15 @@ function dl_test_test2(string $str = ""): string {} class DlTest { public function test(string $str = ""): string {} } + +class DlTestSuperClass { + public int $a; + public function test(string $str = ""): string {} +} + +class DlTestSubClass extends DlTestSuperClass { +} + +/** @alias DlTestClassAlias */ +class DlTestAliasedClass { +} diff --git a/ext/dl_test/dl_test_arginfo.h b/ext/dl_test/dl_test_arginfo.h index 0618bbdb222ca..549ac220b58bc 100644 --- a/ext/dl_test/dl_test_arginfo.h +++ b/ext/dl_test/dl_test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2dbacf5282b0f8e53923ac70495c2da43c7237e3 */ + * Stub hash: 0641a8eeff00e6c8083fe4a8639f970e3ba80db9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -10,10 +10,13 @@ ZEND_END_ARG_INFO() #define arginfo_class_DlTest_test arginfo_dl_test_test2 +#define arginfo_class_DlTestSuperClass_test arginfo_dl_test_test2 + ZEND_FUNCTION(dl_test_test1); ZEND_FUNCTION(dl_test_test2); ZEND_METHOD(DlTest, test); +ZEND_METHOD(DlTestSuperClass, test); static const zend_function_entry ext_functions[] = { @@ -28,6 +31,22 @@ static const zend_function_entry class_DlTest_methods[] = { ZEND_FE_END }; + +static const zend_function_entry class_DlTestSuperClass_methods[] = { + ZEND_ME(DlTestSuperClass, test, arginfo_class_DlTestSuperClass_test, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + +static const zend_function_entry class_DlTestSubClass_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_DlTestAliasedClass_methods[] = { + ZEND_FE_END +}; + static zend_class_entry *register_class_DlTest(void) { zend_class_entry ce, *class_entry; @@ -37,3 +56,40 @@ static zend_class_entry *register_class_DlTest(void) return class_entry; } + +static zend_class_entry *register_class_DlTestSuperClass(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestSuperClass", class_DlTestSuperClass_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + zval property_a_default_value; + ZVAL_UNDEF(&property_a_default_value); + zend_string *property_a_name = zend_string_init("a", sizeof("a") - 1, 1); + zend_declare_typed_property(class_entry, property_a_name, &property_a_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(property_a_name); + + return class_entry; +} + +static zend_class_entry *register_class_DlTestSubClass(zend_class_entry *class_entry_DlTestSuperClass) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestSubClass", class_DlTestSubClass_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_DlTestSuperClass); + + return class_entry; +} + +static zend_class_entry *register_class_DlTestAliasedClass(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestAliasedClass", class_DlTestAliasedClass_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + zend_register_class_alias("DlTestClassAlias", class_entry); + + return class_entry; +} From 867ed156f754af5ea4e269d6695bce03d1128ce9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Mar 2025 19:28:27 +0100 Subject: [PATCH 099/503] Fix GH-18033: NULL-ptr dereference when using register_tick_function in destructor The problem is that `php_request_shutdown` calls `php_deactivate_ticks` prior to running destructors and the shutdown functions and finalizing output handlers. So if a destructor or shutdown function re-registers a tick function, then the user tick functions handler will be added back to `PG(tick_functions)`. When the next request happens, the list `PG(tick_functions)` still contains an entry to call the user tick functions (added in the previous request during shutdown). This causes a NULL deref eventually because `run_user_tick_functions` assumes that if it is called then `BG(user_tick_functions)` must be non-NULL. Fix this by moving the tick handler deactivation. Closes GH-18047. --- NEWS | 2 ++ UPGRADING | 3 +++ Zend/tests/declare/gh18033_1.phpt | 24 ++++++++++++++++++++++++ Zend/tests/declare/gh18033_2.phpt | 16 ++++++++++++++++ main/main.c | 4 ++-- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/declare/gh18033_1.phpt create mode 100644 Zend/tests/declare/gh18033_2.phpt diff --git a/NEWS b/NEWS index bd7c6b3a26ae0..f6b9171d3b51e 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,8 @@ PHP NEWS zend.exception_string_param_max_len=0. (timwolla) . Fixed bug GH-17959 (Relax missing trait fatal error to error exception). (ilutov) + . Fixed bug GH-18033 (NULL-ptr dereference when using register_tick_function + in destructor). (nielsdos) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/UPGRADING b/UPGRADING index 5d372c72e2139..11cca55bd1735 100644 --- a/UPGRADING +++ b/UPGRADING @@ -38,6 +38,9 @@ PHP 8.5 UPGRADE NOTES resources that were indirectly collected through cycles. . It is now allowed to substitute static with self or the concrete class name in final subclasses. + . The tick handlers are now deactivated after all shutdown functions, destructors + have run and the output handlers have been cleaned up. + This is a consequence of fixing GH-18033. - Intl: . The extension now requires at least ICU 57.1. diff --git a/Zend/tests/declare/gh18033_1.phpt b/Zend/tests/declare/gh18033_1.phpt new file mode 100644 index 0000000000000..ccce9360b4651 --- /dev/null +++ b/Zend/tests/declare/gh18033_1.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-18033 (NULL-ptr dereference when using register_tick_function in destructor) +--DESCRIPTION-- +Needs --repeat 2 or something similar to reproduce +--CREDITS-- +clesmian +--FILE-- + +--EXPECT-- +Done +In destructor diff --git a/Zend/tests/declare/gh18033_2.phpt b/Zend/tests/declare/gh18033_2.phpt new file mode 100644 index 0000000000000..8fdcff1b51e6c --- /dev/null +++ b/Zend/tests/declare/gh18033_2.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-18033 (NULL-ptr dereference when using register_tick_function in ob_start) +--DESCRIPTION-- +Needs --repeat 2 or something similar to reproduce +--CREDITS-- +clesmian +--FILE-- + +--EXPECT-- diff --git a/main/main.c b/main/main.c index 4075be8b377e3..415cb02185e94 100644 --- a/main/main.c +++ b/main/main.c @@ -1904,8 +1904,6 @@ void php_request_shutdown(void *dummy) */ EG(current_execute_data) = NULL; - php_deactivate_ticks(); - /* 0. Call any open observer end handlers that are still open after a zend_bailout */ if (ZEND_OBSERVER_ENABLED) { zend_observer_fcall_end_all(); @@ -1926,6 +1924,8 @@ void php_request_shutdown(void *dummy) php_output_end_all(); } zend_end_try(); + php_deactivate_ticks(); + /* 4. Reset max_execution_time (no longer executing php code after response sent) */ zend_try { zend_unset_timeout(); From 843d2a9b5f63e3ed21c6e27cea0db52998c466ec Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Sat, 15 Mar 2025 08:41:14 +0900 Subject: [PATCH 100/503] ext/bcmath: `bc_divide()` small fix (#18060) --- ext/bcmath/libbcmath/src/div.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index ec7619fb77090..ca073a155c766 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -370,12 +370,11 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) while (*numeratorptr == 0) { numeratorptr++; numerator_leading_zeros++; + if (numerator_leading_zeros == numerator_size) { + goto quot_zero; + } } - if (numerator_size > numerator_leading_zeros) { - numerator_size -= numerator_leading_zeros; - } else { - goto quot_zero; - } + numerator_size -= numerator_leading_zeros; /* check and remove divisor leading zeros */ while (*divisorptr == 0) { @@ -396,12 +395,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) divisor_trailing_zeros++; } divisor_size -= divisor_trailing_zeros; - - if (numerator_size > divisor_trailing_zeros) { - numerator_size -= divisor_trailing_zeros; - } else { - goto quot_zero; - } + numerator_size -= divisor_trailing_zeros; size_t quot_size = numerator_size - divisor_size + 1; /* numerator_size >= divisor_size */ if (quot_size > quot_scale) { From 6717947ffe20ac3cd959903545ba5ef5ad1e1e79 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:00:43 +0100 Subject: [PATCH 101/503] Fix GH-18015: Error messages for ldap_mod_replace are confusing Closes GH-18053. --- NEWS | 4 ++++ ext/ldap/ldap.c | 2 +- ext/ldap/tests/ldap_add_error.phpt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index cbf9dd7bd79f2..805363ed24807 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,10 @@ PHP NEWS . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) +- LDAP: + . Fixed bug GH-18015 (Error messages for ldap_mod_replace are confusing). + (nielsdos) + - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 67b01c0ec4472..20245ed56961b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2278,7 +2278,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_P(value); } else { if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(value))) { - zend_argument_value_error(3, "must be an array with numeric keys"); + zend_argument_value_error(3, "attribute \"%s\" must be an array with numeric keys", ZSTR_VAL(attribute)); RETVAL_FALSE; num_berval[i] = 0; num_attribs = i + 1; diff --git a/ext/ldap/tests/ldap_add_error.phpt b/ext/ldap/tests/ldap_add_error.phpt index 5036b3091e835..209a7fb165dc5 100644 --- a/ext/ldap/tests/ldap_add_error.phpt +++ b/ext/ldap/tests/ldap_add_error.phpt @@ -104,7 +104,7 @@ Warning: ldap_add(): Add: Already exists in %s on line %d bool(false) string(14) "Already exists" int(68) -ldap_add(): Argument #3 ($entry) must be an array with numeric keys +ldap_add(): Argument #3 ($entry) attribute "objectClass" must be an array with numeric keys Warning: ldap_add(): Add: Undefined attribute type in %s on line %d bool(false) From 6b6fde90980fbd9de2ebd60e851599b2e7c777c6 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Sat, 15 Mar 2025 08:43:43 +0900 Subject: [PATCH 102/503] ext/bcmath: If size of `BC_VECTOR` array is within 64 bytes, stack area is now used (#18065) --- NEWS | 2 ++ ext/bcmath/libbcmath/src/div.c | 14 ++++++++++++-- ext/bcmath/libbcmath/src/private.h | 3 +++ ext/bcmath/libbcmath/src/recmul.c | 26 +++++++++++++++++--------- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index f6b9171d3b51e..e498fac1d82ef 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - BCMath: . Simplify `bc_divide()` code. (SakiTakamachi) . If the result is 0, n_scale is set to 0. (SakiTakamachi) + . If size of BC_VECTOR array is within 64 bytes, stack area is now used. + (SakiTakamachi) - CLI: . Add --ini=diff to print INI settings changed from the builtin default. diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index ca073a155c766..7da023df9a7e4 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -260,7 +260,15 @@ static void bc_do_div( size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1; size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); - BC_VECTOR *numerator_vectors = safe_emalloc(numerator_arr_size + divisor_arr_size + quot_arr_size, sizeof(BC_VECTOR), 0); + BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; + size_t allocation_arr_size = numerator_arr_size + divisor_arr_size + quot_arr_size; + + BC_VECTOR *numerator_vectors; + if (allocation_arr_size <= BC_STACK_VECTOR_SIZE) { + numerator_vectors = stack_vectors; + } else { + numerator_vectors = safe_emalloc(allocation_arr_size, sizeof(BC_VECTOR), 0); + } BC_VECTOR *divisor_vectors = numerator_vectors + numerator_arr_size; BC_VECTOR *quot_vectors = divisor_vectors + divisor_arr_size; @@ -302,7 +310,9 @@ static void bc_do_div( quot_vectors[i] /= BASE; } - efree(numerator_vectors); + if (allocation_arr_size > BC_STACK_VECTOR_SIZE) { + efree(numerator_vectors); + } } static inline void bc_divide_by_one(bc_num numerator, bc_num *quot, size_t quot_scale) diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 1a911442dc9a1..7e972952c75e3 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -64,6 +64,9 @@ # define BC_LITTLE_ENDIAN 1 #endif +/* 64-bytes for 64-bit */ +#define BC_STACK_VECTOR_SIZE 8 + /* * Adding more than this many times may cause uint32_t/uint64_t to overflow. * Typically this is 1844 for 64bit and 42 for 32bit. diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index de06a4ca037ec..fc7efb37ebf02 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -149,15 +149,21 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc size_t n2_arr_size = (n2len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - /* - * let's say that N is the max of n1len and n2len (and a multiple of BC_VECTOR_SIZE for simplicity), - * then this sum is <= N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE - 1 - * which is equal to N - 1 if BC_VECTOR_SIZE is 4, and N/2 - 1 if BC_VECTOR_SIZE is 8. - */ - BC_VECTOR *buf = safe_emalloc(n1_arr_size + n2_arr_size + prod_arr_size, sizeof(BC_VECTOR), 0); + BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; + size_t allocation_arr_size = n1_arr_size + n2_arr_size + prod_arr_size; - BC_VECTOR *n1_vector = buf; - BC_VECTOR *n2_vector = buf + n1_arr_size; + BC_VECTOR *n1_vector; + if (allocation_arr_size <= BC_STACK_VECTOR_SIZE) { + n1_vector = stack_vectors; + } else { + /* + * let's say that N is the max of n1len and n2len (and a multiple of BC_VECTOR_SIZE for simplicity), + * then this sum is <= N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE - 1 + * which is equal to N - 1 if BC_VECTOR_SIZE is 4, and N/2 - 1 if BC_VECTOR_SIZE is 8. + */ + n1_vector = safe_emalloc(allocation_arr_size, sizeof(BC_VECTOR), 0); + } + BC_VECTOR *n2_vector = n1_vector + n1_arr_size; BC_VECTOR *prod_vector = n2_vector + n2_arr_size; for (i = 0; i < prod_arr_size; i++) { @@ -188,7 +194,9 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc bc_mul_finish_from_vector(prod_vector, prod_arr_size, prodlen, prod); - efree(buf); + if (allocation_arr_size > BC_STACK_VECTOR_SIZE) { + efree(n1_vector); + } } /** This is bc_standard_mul implementation for square */ From e96a35b9a8a55653e4adef529298e1587f9a33cc Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sat, 15 Mar 2025 08:50:55 +0900 Subject: [PATCH 103/503] Fixed pdo_firebird_handle_factory to check ret when starting a transaction (#17632) Changed to not execute php_firebird_begin_transaction if transaction cannot be started successfully Closes #17632 --- ext/pdo_firebird/firebird_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 08764ecf45a30..136483a149696 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -684,7 +684,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */ /* make all parameters nullable */ unsigned int i; - XSQLVAR* var; + XSQLVAR* var; for (i = 0, var = S->in_sqlda->sqlvar; i < S->in_sqlda->sqld; i++, var++) { /* The low bit of sqltype indicates that the parameter can take a NULL value */ var->sqltype |= 1; @@ -1431,7 +1431,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* "HY000", H->isc_status[1], errmsg); } - if (dbh->auto_commit && !H->tr) { + if (ret && dbh->auto_commit && !H->tr) { ret = php_firebird_begin_transaction(dbh, /* auto commit mode */ true); } From f34859cb9050dc240f48015195bee731d0233764 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 13 Mar 2025 20:46:52 +0000 Subject: [PATCH 104/503] ext/intl: Fix dateformat_format when the time is an array of references. --- NEWS | 2 ++ ext/intl/dateformat/dateformat_format.c | 2 +- .../tests/dateformat_format_references.phpt | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/dateformat_format_references.phpt diff --git a/NEWS b/NEWS index 3f4b5aa2bc83a..8f5c84781e5db 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ PHP NEWS - Intl: . Fix locale_compose and locale_lookup to work with their array argument with values as references. (David Carlier) + . Fix dateformat_format when the time is an array of references. + (David Carlier) - Embed: . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) diff --git a/ext/intl/dateformat/dateformat_format.c b/ext/intl/dateformat/dateformat_format.c index 9419469b4f609..928712934b15c 100644 --- a/ext/intl/dateformat/dateformat_format.c +++ b/ext/intl/dateformat/dateformat_format.c @@ -64,7 +64,7 @@ static int32_t internal_get_arr_ele(IntlDateFormatter_object *dfo, return result; } - if ((ele_value = zend_hash_str_find(hash_arr, key_name, strlen(key_name))) != NULL) { + if ((ele_value = zend_hash_str_find_deref(hash_arr, key_name, strlen(key_name))) != NULL) { if(Z_TYPE_P(ele_value) != IS_LONG) { spprintf(&message, 0, "datefmt_format: parameter array contains " "a non-integer element for key '%s'", key_name); diff --git a/ext/intl/tests/dateformat_format_references.phpt b/ext/intl/tests/dateformat_format_references.phpt new file mode 100644 index 0000000000000..da1a52955f121 --- /dev/null +++ b/ext/intl/tests/dateformat_format_references.phpt @@ -0,0 +1,23 @@ +--TEST-- +Fix dateformat_format() with array argument with values as references. +--SKIPIF-- + +--FILE-- + &$a , + 'tm_min' => 3, + 'tm_hour' => 19, + 'tm_mday' => 3, + 'tm_mon' => 3, + 'tm_year' => 105, +); +$fmt = datefmt_create('en_US', IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/New_York', IntlDateFormatter::GREGORIAN); +$formatted = datefmt_format($fmt , $localtime_arr); +var_dump($formatted); +?> +--EXPECTF-- +string(%d) "Sunday, April 3, 2005 at 7:03:24%aPM Eastern Daylight Time" From 005c7b57974ede27e2714a9bfca534d595985e58 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 14 Mar 2025 07:36:48 +0000 Subject: [PATCH 105/503] ext/intl: Fix Uconverter::transcode with substitutes as references. close GH-18059 --- NEWS | 1 + ext/intl/converter/converter.c | 4 ++-- .../uconverter_transcode_references.phpt | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 ext/intl/tests/uconverter_transcode_references.phpt diff --git a/NEWS b/NEWS index 8f5c84781e5db..8c9400b4a66c3 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,7 @@ PHP NEWS with values as references. (David Carlier) . Fix dateformat_format when the time is an array of references. (David Carlier) + . Fix UConverter::transcode with substitutes as references. (David Carlier) - Embed: . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c index 75fbfbc8e8861..4342eabcaf9eb 100644 --- a/ext/intl/converter/converter.c +++ b/ext/intl/converter/converter.c @@ -749,13 +749,13 @@ PHP_METHOD(UConverter, transcode) { zval *tmpzval; if (U_SUCCESS(error) && - (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL && + (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL && Z_TYPE_P(tmpzval) == IS_STRING) { error = U_ZERO_ERROR; ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); } if (U_SUCCESS(error) && - (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL && + (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL && Z_TYPE_P(tmpzval) == IS_STRING) { error = U_ZERO_ERROR; ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); diff --git a/ext/intl/tests/uconverter_transcode_references.phpt b/ext/intl/tests/uconverter_transcode_references.phpt new file mode 100644 index 0000000000000..a2b1be20d1dfe --- /dev/null +++ b/ext/intl/tests/uconverter_transcode_references.phpt @@ -0,0 +1,22 @@ +--TEST-- +UConverter::transcode issue with substitutes values as references +--EXTENSIONS-- +intl +--FILE-- + '?', 'to_subst' => &$subst); +var_dump(UConverter::transcode("This is an ascii string", 'ascii', 'utf-8', $opts)); +$opts = array('from_subst' => &$subst, 'to_subst' => '?'); +var_dump(UConverter::transcode("This is an ascii string", 'ascii', 'utf-8', $opts)); +// should yield the same results +$opts = array('from_subst' => '?', 'to_subst' => '??'); +var_dump(UConverter::transcode("This is an ascii string", 'ascii', 'utf-8', $opts)); +$opts = array('from_subst' => '??', 'to_subst' => '?'); +var_dump(UConverter::transcode("This is an ascii string", 'ascii', 'utf-8', $opts)); +?> +--EXPECT-- +bool(false) +string(23) "This is an ascii string" +bool(false) +string(23) "This is an ascii string" From c5f6a8b0a2ae94858e7c94fb7aecf4bc5246fec8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 15 Mar 2025 14:40:39 +0100 Subject: [PATCH 106/503] Minor improvements to ext/xml memory management (#18071) --- ext/xml/xml.c | 112 ++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 8394bbf3cb31b..bf9f747599730 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -86,7 +86,7 @@ typedef struct { int toffset; int curtag; zend_long ctag_index; - char **ltags; + zend_string **ltags; bool lastwasopen; bool skipwhite; bool isparsing; @@ -116,8 +116,6 @@ ZEND_GET_MODULE(xml) #define XML_MAXLEVEL 255 /* XXX this should be dynamic */ -#define SKIP_TAGSTART(str) ((str) + (parser->toffset > strlen(str) ? strlen(str) : parser->toffset)) - static zend_class_entry *xml_parser_ce; static zend_object_handlers xml_parser_object_handlers; @@ -138,7 +136,7 @@ inline static unsigned short xml_encode_us_ascii(unsigned char); inline static char xml_decode_us_ascii(unsigned short); static void xml_xmlchar_zval(const XML_Char *, int, const XML_Char *, zval *); static int xml_xmlcharlen(const XML_Char *); -static void xml_add_to_info(xml_parser *parser, const char *name); +static void xml_add_to_info(xml_parser *parser, zend_string *name); inline static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag); void xml_startElementHandler(void *, const XML_Char *, const XML_Char **); @@ -311,7 +309,6 @@ static inline xml_parser *xml_parser_from_obj(zend_object *obj) { static zend_object *xml_parser_create_object(zend_class_entry *class_type) { xml_parser *intern = zend_object_alloc(sizeof(xml_parser), class_type); - memset(intern, 0, sizeof(xml_parser) - sizeof(zend_object)); zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); @@ -323,8 +320,11 @@ static void xml_parser_free_ltags(xml_parser *parser) { if (parser->ltags) { int inx; - for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++) - efree(parser->ltags[ inx ]); + for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++) { + if (parser->ltags[inx]) { + zend_string_release_ex(parser->ltags[inx], false); + } + } efree(parser->ltags); } } @@ -553,7 +553,7 @@ static int xml_xmlcharlen(const XML_Char *s) /* }}} */ /* {{{ xml_add_to_info() */ -static void xml_add_to_info(xml_parser *parser, const char *name) +static void xml_add_to_info(xml_parser *parser, zend_string *name) { zval *element; @@ -564,11 +564,10 @@ static void xml_add_to_info(xml_parser *parser, const char *name) SEPARATE_ARRAY(Z_REFVAL(parser->info)); zend_array *arr = Z_ARRVAL_P(Z_REFVAL(parser->info)); - size_t name_len = strlen(name); - if ((element = zend_hash_str_find(arr, name, name_len)) == NULL) { + if ((element = zend_hash_find(arr, name)) == NULL) { zval values; array_init(&values); - element = zend_hash_str_update(arr, name, name_len, &values); + element = zend_hash_update(arr, name, &values); } add_next_index_long(element, parser->curtag); @@ -592,6 +591,17 @@ static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag) } /* }}} */ +static zend_string *xml_stripped_tag(zend_string *tag_name, int offset) +{ + if (offset == 0) { + return zend_string_copy(tag_name); + } else if (offset >= ZSTR_LEN(tag_name)) { + return ZSTR_EMPTY_ALLOC(); + } else { + return zend_string_init(ZSTR_VAL(tag_name) + offset, ZSTR_LEN(tag_name) - offset, false); + } +} + static zval *xml_get_separated_data(xml_parser *parser) { if (EXPECTED(Z_TYPE_P(Z_REFVAL(parser->data)) == IS_ARRAY)) { @@ -632,7 +642,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha if (ZEND_FCC_INITIALIZED(parser->startElementHandler)) { zval args[3]; ZVAL_COPY(&args[0], &parser->index); - ZVAL_STRING(&args[1], SKIP_TAGSTART(ZSTR_VAL(tag_name))); + ZVAL_STR(&args[1], xml_stripped_tag(tag_name, parser->toffset)); array_init(&args[2]); while (attributes && *attributes) { @@ -651,7 +661,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha zend_call_known_fcc(&parser->startElementHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); + zval_ptr_dtor_str(&args[1]); zval_ptr_dtor(&args[2]); } @@ -663,15 +673,15 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha array_init(&tag); array_init(&atr); - char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name)); - - xml_add_to_info(parser, skipped_tag_name); + zend_string *stripped_tag = xml_stripped_tag(tag_name, parser->toffset); + xml_add_to_info(parser, stripped_tag); - add_assoc_string(&tag, "tag", skipped_tag_name); + add_assoc_str(&tag, "tag", stripped_tag); /* transfer lifetime */ add_assoc_string(&tag, "type", "open"); add_assoc_long(&tag, "level", parser->level); - parser->ltags[parser->level-1] = estrdup(ZSTR_VAL(tag_name)); + /* Because toffset may change, we should use the original tag name */ + parser->ltags[parser->level - 1] = zend_string_copy(tag_name); parser->lastwasopen = 1; attributes = (const XML_Char **) attrs; @@ -733,11 +743,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name) if (ZEND_FCC_INITIALIZED(parser->endElementHandler)) { zval args[2]; ZVAL_COPY(&args[0], &parser->index); - ZVAL_STRING(&args[1], SKIP_TAGSTART(ZSTR_VAL(tag_name))); + ZVAL_STR(&args[1], xml_stripped_tag(tag_name, parser->toffset)); zend_call_known_fcc(&parser->endElementHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); + zval_ptr_dtor_str(&args[1]); } if (!Z_ISUNDEF(parser->data) && !EG(exception)) { @@ -749,17 +759,19 @@ void xml_endElementHandler(void *userData, const XML_Char *name) add_assoc_string(zv, "type", "complete"); } } else { - char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name)); + zend_string *stripped_tag = xml_stripped_tag(tag_name, parser->toffset); - xml_add_to_info(parser, skipped_tag_name); + xml_add_to_info(parser, stripped_tag); zval *data = xml_get_separated_data(parser); if (EXPECTED(data)) { array_init(&tag); - add_assoc_string(&tag, "tag", skipped_tag_name); + add_assoc_str(&tag, "tag", stripped_tag); /* transfer lifetime */ add_assoc_string(&tag, "type", "close"); add_assoc_long(&tag, "level", parser->level); zend_hash_next_index_insert(Z_ARRVAL_P(data), &tag); + } else { + zend_string_release_ex(stripped_tag, false); } } @@ -769,7 +781,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name) zend_string_release_ex(tag_name, 0); if ((parser->ltags) && (parser->level <= XML_MAXLEVEL)) { - efree(parser->ltags[parser->level-1]); + zend_string **str = &parser->ltags[parser->level - 1]; + if (*str) { + zend_string_release_ex(*str, false); + *str = NULL; + } } parser->level--; @@ -792,7 +808,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len) zend_call_known_fcc(&parser->characterDataHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); + zval_ptr_dtor_str(&args[1]); } if (Z_ISUNDEF(parser->data) || EG(exception)) { @@ -868,8 +884,9 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len) } ZEND_HASH_FOREACH_END(); if (parser->level <= XML_MAXLEVEL && parser->level > 0 && (doprint || (! parser->skipwhite))) { array_init(&tag); - xml_add_to_info(parser,SKIP_TAGSTART(parser->ltags[parser->level-1])); - add_assoc_string(&tag, "tag", SKIP_TAGSTART(parser->ltags[parser->level-1])); + zend_string *stripped_tag = xml_stripped_tag(parser->ltags[parser->level - 1], parser->toffset); + xml_add_to_info(parser, stripped_tag); + add_assoc_str(&tag, "tag", stripped_tag); /* transfer lifetime */ add_assoc_str(&tag, "value", decoded_value); add_assoc_string(&tag, "type", "cdata"); add_assoc_long(&tag, "level", parser->level); @@ -900,8 +917,8 @@ void xml_processingInstructionHandler(void *userData, const XML_Char *target, co zend_call_known_fcc(&parser->processingInstructionHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); + zval_ptr_dtor_str(&args[1]); + zval_ptr_dtor_str(&args[2]); } /* }}} */ @@ -921,7 +938,7 @@ void xml_defaultHandler(void *userData, const XML_Char *s, int len) zend_call_known_fcc(&parser->defaultHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); + zval_ptr_dtor_str(&args[1]); } /* }}} */ @@ -947,11 +964,11 @@ void xml_unparsedEntityDeclHandler(void *userData, zend_call_known_fcc(&parser->unparsedEntityDeclHandler, /* retval */ NULL, /* param_count */ 6, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[3]); - zval_ptr_dtor(&args[4]); - zval_ptr_dtor(&args[5]); + zval_ptr_dtor_str(&args[1]); + zval_ptr_dtor_str(&args[2]); + zval_ptr_dtor_str(&args[3]); + zval_ptr_dtor_str(&args[4]); + zval_ptr_dtor_str(&args[5]); } /* }}} */ @@ -975,10 +992,10 @@ void xml_notationDeclHandler(void *userData, const XML_Char *notationName, zend_call_known_fcc(&parser->notationDeclHandler, /* retval */ NULL, /* param_count */ 5, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[3]); - zval_ptr_dtor(&args[4]); + zval_ptr_dtor_str(&args[1]); + zval_ptr_dtor_str(&args[2]); + zval_ptr_dtor_str(&args[3]); + zval_ptr_dtor_str(&args[4]); } /* }}} */ @@ -1004,10 +1021,10 @@ int xml_externalEntityRefHandler(XML_Parser userData, const XML_Char *openEntity zend_call_known_fcc(&parser->externalEntityRefHandler, /* retval */ &retval, /* param_count */ 5, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[3]); - zval_ptr_dtor(&args[4]); + zval_ptr_dtor_str(&args[1]); + zval_ptr_dtor_str(&args[2]); + zval_ptr_dtor_str(&args[3]); + zval_ptr_dtor_str(&args[4]); /* TODO Better handling from callable return value */ if (!Z_ISUNDEF(retval)) { @@ -1037,8 +1054,8 @@ void xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const zend_call_known_fcc(&parser->startNamespaceDeclHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); + zval_ptr_dtor_str(&args[1]); + zval_ptr_dtor_str(&args[2]); } /* }}} */ @@ -1058,7 +1075,7 @@ void xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix) zend_call_known_fcc(&parser->endNamespaceDeclHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); + zval_ptr_dtor_str(&args[1]); } /* }}} */ @@ -1448,8 +1465,7 @@ PHP_FUNCTION(xml_parse_into_struct) parser->level = 0; xml_parser_free_ltags(parser); - parser->ltags = safe_emalloc(XML_MAXLEVEL, sizeof(char *), 0); - memset(parser->ltags, 0, XML_MAXLEVEL * sizeof(char *)); + parser->ltags = ecalloc(XML_MAXLEVEL, sizeof(zend_string *)); XML_SetElementHandler(parser->parser, xml_startElementHandler, xml_endElementHandler); XML_SetCharacterDataHandler(parser->parser, xml_characterDataHandler); From d8e7f362dd0943f8712acbc3bbf76d2edcf52d75 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 15 Mar 2025 18:14:33 +0000 Subject: [PATCH 107/503] ext/curl: Various minor clean-up refactorings (#18042) --- ext/curl/interface.c | 9 ++++----- ext/curl/multi.c | 8 ++------ ext/curl/share.c | 8 ++------ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 311b2f7cc8a59..5be9327566b19 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -843,7 +843,7 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) { php_curl *ch = (php_curl *)ctx; php_curl_read *read_handler = ch->handlers.read; - int length = 0; + size_t length = 0; switch (read_handler->method) { case PHP_CURL_DIRECT: @@ -1184,7 +1184,6 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode) array_init(&certhash); for (slist = ci->certinfo[i]; slist; slist = slist->next) { - int len; char s[64]; char *tmp; strncpy(s, slist->data, sizeof(s)); @@ -1192,7 +1191,7 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode) tmp = memchr(s, ':', sizeof(s)); if(tmp) { *tmp = '\0'; - len = strlen(s); + size_t len = strlen(s); add_assoc_string(&certhash, s, &slist->data[len+1]); } else { php_error_docref(NULL, E_WARNING, "Could not extract hash key from certificate info"); @@ -1445,7 +1444,6 @@ static inline zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpo zval *prop, rv; char *type = NULL, *filename = NULL; struct mime_data_cb_arg *cb_arg; - php_stream *stream; php_stream_statbuf ssb; size_t filesize = -1; curl_seek_callback seekfunc = seek_cb; @@ -1475,6 +1473,7 @@ static inline zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpo zval_ptr_dtor(&ch->postfields); ZVAL_COPY(&ch->postfields, zpostfields); + php_stream *stream; if ((stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", STREAM_MUST_SEEK, NULL))) { if (!stream->readfilters.head && !php_stream_stat(stream, &ssb)) { filesize = ssb.sb.st_size; @@ -2409,7 +2408,7 @@ PHP_FUNCTION(curl_setopt_array) ch = Z_CURL_P(zid); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(arr), option, string_key, entry) { - if (string_key) { + if (UNEXPECTED(string_key)) { zend_argument_value_error(2, "contains an invalid cURL option"); RETURN_THROWS(); } diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 938393f410e70..3d97b581be764 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -403,7 +403,7 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea php_curl *ch; php_curl *parent; php_curlm *mh = (php_curlm *)userp; - size_t rval = CURL_PUSH_DENY; + int rval = CURL_PUSH_DENY; zval *pz_parent_ch = NULL; zval pz_ch; zval headers; @@ -524,11 +524,7 @@ PHP_FUNCTION(curl_multi_setopt) mh = Z_CURL_MULTI_P(z_mh); - if (_php_curl_multi_setopt(mh, options, zvalue, return_value)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(_php_curl_multi_setopt(mh, options, zvalue, return_value)); } /* }}} */ diff --git a/ext/curl/share.c b/ext/curl/share.c index 8f3bb7543a20f..e5f9e3d807dc2 100644 --- a/ext/curl/share.c +++ b/ext/curl/share.c @@ -54,7 +54,7 @@ PHP_FUNCTION(curl_share_close) } /* }}} */ -static bool _php_curl_share_setopt(php_curlsh *sh, zend_long option, zval *zvalue, zval *return_value) /* {{{ */ +static bool _php_curl_share_setopt(php_curlsh *sh, zend_long option, const zval *zvalue) /* {{{ */ { CURLSHcode error = CURLSHE_OK; @@ -91,11 +91,7 @@ PHP_FUNCTION(curl_share_setopt) sh = Z_CURL_SHARE_P(z_sh); - if (_php_curl_share_setopt(sh, options, zvalue, return_value)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(_php_curl_share_setopt(sh, options, zvalue)); } /* }}} */ From 4fd99925617be65f19c2a026610041c86777f8a2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:31:40 +0100 Subject: [PATCH 108/503] Fix OSS-Fuzz #403308724 Because simple hooks can be nested without starting a new context, we need to restore the old property info in case of nested hooks. Closes GH-18074. --- NEWS | 1 + .../property_hooks/oss_fuzz_403308724.phpt | 30 +++++++++++++++++++ Zend/zend_compile.c | 4 +-- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/property_hooks/oss_fuzz_403308724.phpt diff --git a/NEWS b/NEWS index 805363ed24807..f912002aebdbf 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,7 @@ PHP NEWS (Arnaud) . Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown). (Arnaud) + . Fixed OSS-Fuzz #403308724. (nielsdos) - DBA: . Fixed assertion violation when opening the same file with dba_open diff --git a/Zend/tests/property_hooks/oss_fuzz_403308724.phpt b/Zend/tests/property_hooks/oss_fuzz_403308724.phpt new file mode 100644 index 0000000000000..b27b08dd703b6 --- /dev/null +++ b/Zend/tests/property_hooks/oss_fuzz_403308724.phpt @@ -0,0 +1,30 @@ +--TEST-- +OSS-Fuzz #403308724 +--FILE-- + 1; } +} + +class Test extends Base { + public $y { + get => [new class { + public $inner {get => __PROPERTY__;} + }, parent::$y::get()]; + } +} + +$test = new Test; +$y = $test->y; +var_dump($y); +var_dump($y[0]->inner); +?> +--EXPECT-- +array(2) { + [0]=> + object(class@anonymous)#2 (0) { + } + [1]=> + int(1) +} +string(5) "inner" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ef75b45ad0528..832dedc421042 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8645,7 +8645,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f /* FIXME: This is a dirty fix to maintain ABI compatibility. We don't * have an actual property info yet, but we really only need the name * anyway. We should convert this to a zend_string. */ - ZEND_ASSERT(!CG(context).active_property_info); + const zend_property_info *old_active_property_info = CG(context).active_property_info; zend_property_info dummy_prop_info = { .name = name }; CG(context).active_property_info = &dummy_prop_info; @@ -8742,7 +8742,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, 0); } - CG(context).active_property_info = NULL; + CG(context).active_property_info = old_active_property_info; } } /* }}} */ From 45fc03c190002f0a76fda604b0d7703ec87b0b1f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 15 Mar 2025 19:35:14 +0100 Subject: [PATCH 109/503] Fix mysql test date flakiness Separate date() calls can lead to diverging results. Closes GH-18080 --- ...mysqli_fetch_all_data_types_variation.phpt | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt index 69fc427001fd0..594980ec0f829 100644 --- a/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt +++ b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt @@ -122,22 +122,27 @@ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", "99999999.99", "99999999. func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", NULL, NULL, 400); // don't care about date() strict TZ warnings... -func_mysqli_fetch_all($link, $engine, "DATE", @date('Y-m-d'), @date('Y-m-d'), 410); -func_mysqli_fetch_all($link, $engine, "DATE NOT NULL", @date('Y-m-d'), @date('Y-m-d'), 420); +$date = @date('Y-m-d'); +$datetime = @date('Y-m-d H:i:s'); +$time = @date('H:i:s'); +$year = @date('Y'); + +func_mysqli_fetch_all($link, $engine, "DATE", $date, $date, 410); +func_mysqli_fetch_all($link, $engine, "DATE NOT NULL", $date, $date, 420); func_mysqli_fetch_all($link, $engine, "DATE", NULL, NULL, 430); -func_mysqli_fetch_all($link, $engine, "DATETIME", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 440); -func_mysqli_fetch_all($link, $engine, "DATETIME NOT NULL", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 450); +func_mysqli_fetch_all($link, $engine, "DATETIME", $datetime, $datetime, 440); +func_mysqli_fetch_all($link, $engine, "DATETIME NOT NULL", $datetime, $datetime, 450); func_mysqli_fetch_all($link, $engine, "DATETIME", NULL, NULL, 460); -func_mysqli_fetch_all($link, $engine, "TIMESTAMP", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 470); +func_mysqli_fetch_all($link, $engine, "TIMESTAMP", $datetime, $datetime, 470); -func_mysqli_fetch_all($link, $engine, "TIME", @date('H:i:s'), @date('H:i:s'), 480); -func_mysqli_fetch_all($link, $engine, "TIME NOT NULL", @date('H:i:s'), @date('H:i:s'), 490); +func_mysqli_fetch_all($link, $engine, "TIME", $time, $time, 480); +func_mysqli_fetch_all($link, $engine, "TIME NOT NULL", $time, $time, 490); func_mysqli_fetch_all($link, $engine, "TIME", NULL, NULL, 500); -func_mysqli_fetch_all($link, $engine, "YEAR", @date('Y'), @date('Y'), 510); -func_mysqli_fetch_all($link, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520); +func_mysqli_fetch_all($link, $engine, "YEAR", $year, $year, 510); +func_mysqli_fetch_all($link, $engine, "YEAR NOT NULL", $year, $year, 520); func_mysqli_fetch_all($link, $engine, "YEAR", NULL, NULL, 530); $string255 = func_mysqli_fetch_array_make_string(255); From 38e553e4182437111432841651cca1c6ce2a8632 Mon Sep 17 00:00:00 2001 From: Katherine456719 Date: Sat, 15 Mar 2025 23:24:06 +0200 Subject: [PATCH 110/503] Fix GH-18082: Memory leaks in fuzzer SAPI error paths Closes GH-18081. --- NEWS | 4 ++++ sapi/fuzzer/fuzzer-json.c | 11 +++++------ sapi/fuzzer/fuzzer-mbregex.c | 9 +++++---- sapi/fuzzer/fuzzer-unserialize.c | 7 ++++--- sapi/fuzzer/fuzzer-unserializehash.c | 8 ++++---- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index 8c9400b4a66c3..59b66e85f84f9 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,10 @@ PHP NEWS - Embed: . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) +- Fuzzer: + . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI). + (Lung-Alexandra) + - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) diff --git a/sapi/fuzzer/fuzzer-json.c b/sapi/fuzzer/fuzzer-json.c index 4335598bc3caa..f5c00d77d9942 100644 --- a/sapi/fuzzer/fuzzer-json.c +++ b/sapi/fuzzer/fuzzer-json.c @@ -15,8 +15,6 @@ +----------------------------------------------------------------------+ */ - - #include "fuzzer.h" #include "Zend/zend.h" @@ -31,14 +29,15 @@ #include "ext/json/php_json_parser.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - char *data = malloc(Size+1); - memcpy(data, Data, Size); - data[Size] = '\0'; - if (fuzzer_request_startup() == FAILURE) { + if (fuzzer_request_startup() == FAILURE){ return 0; } + char *data = malloc(Size + 1); + memcpy(data, Data, Size); + data[Size] = '\0'; + for (int option = 0; option <=1; ++option) { zval result; php_json_parser parser; diff --git a/sapi/fuzzer/fuzzer-mbregex.c b/sapi/fuzzer/fuzzer-mbregex.c index 970a7b5baeedb..afcd2b5c1ba7e 100644 --- a/sapi/fuzzer/fuzzer-mbregex.c +++ b/sapi/fuzzer/fuzzer-mbregex.c @@ -30,15 +30,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { #ifdef HAVE_MBREGEX - char *args[2]; - char *data = malloc(Size+1); - memcpy(data, Data, Size); - data[Size] = '\0'; if (fuzzer_request_startup() == FAILURE) { return 0; } + char *args[2]; + char *data = malloc(Size+1); + memcpy(data, Data, Size); + data[Size] = '\0'; + fuzzer_setup_dummy_frame(); args[0] = data; diff --git a/sapi/fuzzer/fuzzer-unserialize.c b/sapi/fuzzer/fuzzer-unserialize.c index ff26e5b1e8da3..d58b35ca32bd1 100644 --- a/sapi/fuzzer/fuzzer-unserialize.c +++ b/sapi/fuzzer/fuzzer-unserialize.c @@ -30,14 +30,15 @@ #include "ext/standard/php_var.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - unsigned char *orig_data = malloc(Size+1); - memcpy(orig_data, Data, Size); - orig_data[Size] = '\0'; if (fuzzer_request_startup() == FAILURE) { return 0; } + unsigned char *orig_data = malloc(Size+1); + memcpy(orig_data, Data, Size); + orig_data[Size] = '\0'; + fuzzer_setup_dummy_frame(); { diff --git a/sapi/fuzzer/fuzzer-unserializehash.c b/sapi/fuzzer/fuzzer-unserializehash.c index 5d29eb5fb8c61..03c64dcbca017 100644 --- a/sapi/fuzzer/fuzzer-unserializehash.c +++ b/sapi/fuzzer/fuzzer-unserializehash.c @@ -34,15 +34,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t FullSize) { } ++Start; + if (fuzzer_request_startup() == FAILURE) { + return 0; + } + size_t Size = (Data + FullSize) - Start; unsigned char *orig_data = malloc(Size+1); memcpy(orig_data, Start, Size); orig_data[Size] = '\0'; - if (fuzzer_request_startup() == FAILURE) { - return 0; - } - fuzzer_setup_dummy_frame(); { From 2df4ade39bb978bae3811882687854ec483c1beb Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:16:07 -0800 Subject: [PATCH 111/503] gen_stub: reduce the number of public properties The following properties are made private: * `ArrayType::$keyType`, `::$valueType` * `ArginfoType::$builtinTypes` * `ConstName::$const` * `ClassConstName::$const` * `PropertyName::$property` * `FuncInfo::$classFlags`, `::$isDeprecated`, `::$supportsCompileTimeEval`, `::$minimumPhpVersionIdCompatibility`, `::$framelessFunctionInfos`, `::$exposedDocComment` * `VariableLike::$link` * `ConstInfo::$isDeprecated`, `::$valueString`, `::$isFileCacheAllowed` * `PropertyInfo::$classFlags`, `::$defaultValue`, `::$defaultValueString`, `::$isDocReadonly`, `::$isVirtual` * `EnumCaseInfo::$name`, `::$value` * `AttributeInfo::$args` * `ClassInfo::$enumBackingType`, `::$isDeprecated`, `::$exposedDocComment`, `::$isStrictProperties`, `::$isNotSerializable`, `::$propertyInfos`, `::$enumCaseInfos` The following are made protected: * `VariableLike::$exposedDocComment`, `::$phpVersionIdMinimumCompatibility` --- build/gen_stub.php | 64 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index f060cc1cebae0..1734c67744492 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -185,8 +185,8 @@ class Context { } class ArrayType extends SimpleType { - public /* readonly */ Type $keyType; - public /* readonly */ Type $valueType; + private /* readonly */ Type $keyType; + private /* readonly */ Type $valueType; public static function createGenericArray(): self { @@ -877,7 +877,7 @@ public function isUnknown(): bool } class ConstName extends AbstractConstName { - public /* readonly */ string $const; + private /* readonly */ string $const; public function __construct(?Name $namespace, string $const) { @@ -914,7 +914,7 @@ public function getDeclarationName(): string class ClassConstName extends AbstractConstName { public /* readonly */ Name $class; - public /* readonly */ string $const; + private /* readonly */ string $const; public function __construct(Name $class, string $const) { @@ -940,7 +940,7 @@ public function getDeclarationName(): string class PropertyName implements VariableLikeName { public /* readonly */ Name $class; - public /* readonly */ string $property; + private /* readonly */ string $property; public function __construct(Name $class, string $property) { @@ -1148,12 +1148,12 @@ private function setRefcount(?string $refcount): void class FuncInfo { public /* readonly */ FunctionOrMethodName $name; - public /* readonly */ int $classFlags; + private /* readonly */ int $classFlags; public int $flags; public /* readonly */ ?string $aliasType; public ?FunctionOrMethodName $alias; - public /* readonly */ bool $isDeprecated; - public bool $supportsCompileTimeEval; + private /* readonly */ bool $isDeprecated; + private bool $supportsCompileTimeEval; public /* readonly */ bool $verify; /** @var ArgInfo[] */ public /* readonly */ array $args; @@ -1161,12 +1161,12 @@ class FuncInfo { public /* readonly */ int $numRequiredArgs; public /* readonly */ ?string $cond; public bool $isUndocumentable; - public ?int $minimumPhpVersionIdCompatibility; + private ?int $minimumPhpVersionIdCompatibility; /** @var AttributeInfo[] */ public array $attributes; /** @var FramelessFunctionInfo[] */ - public array $framelessFunctionInfos; - public ?ExposedDocComment $exposedDocComment; + private array $framelessFunctionInfos; + private ?ExposedDocComment $exposedDocComment; /** * @param ArgInfo[] $args @@ -2274,11 +2274,11 @@ abstract class VariableLike public int $flags; public ?Type $type; public /* readonly */ ?Type $phpDocType; - public /* readonly */ ?string $link; - public ?int $phpVersionIdMinimumCompatibility; + private /* readonly */ ?string $link; + protected ?int $phpVersionIdMinimumCompatibility; /** @var AttributeInfo[] */ public array $attributes; - public /* readonly */ ?ExposedDocComment $exposedDocComment; + protected /* readonly */ ?ExposedDocComment $exposedDocComment; /** * @var AttributeInfo[] $attributes @@ -2456,12 +2456,12 @@ class ConstInfo extends VariableLike { public /* readonly */ AbstractConstName $name; public /* readonly */ Expr $value; - public bool $isDeprecated; - public /* readonly */ ?string $valueString; + private bool $isDeprecated; + private /* readonly */ ?string $valueString; public /* readonly */ ?string $cond; public /* readonly */ ?string $cValue; public /* readonly */ bool $isUndocumentable; - public /* readonly */ bool $isFileCacheAllowed; + private /* readonly */ bool $isFileCacheAllowed; /** * @var AttributeInfo[] $attributes @@ -2814,12 +2814,12 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie class PropertyInfo extends VariableLike { - public /* readonly */ int $classFlags; + private /* readonly */ int $classFlags; public /* readonly */ PropertyName $name; - public /* readonly */ ?Expr $defaultValue; - public /* readonly */ ?string $defaultValueString; - public /* readonly */ bool $isDocReadonly; - public /* readonly */ bool $isVirtual; + private /* readonly */ ?Expr $defaultValue; + private /* readonly */ ?string $defaultValueString; + private /* readonly */ bool $isDocReadonly; + private /* readonly */ bool $isVirtual; // Map possible variable names to the known string constant, see // ZEND_KNOWN_STRINGS @@ -3149,8 +3149,8 @@ public function __clone() } class EnumCaseInfo { - public /* readonly */ string $name; - public /* readonly */ ?Expr $value; + private /* readonly */ string $name; + private /* readonly */ ?Expr $value; public function __construct(string $name, ?Expr $value) { $this->name = $name; @@ -3179,7 +3179,7 @@ public function getDeclaration(array $allConstInfos): string { class AttributeInfo { public /* readonly */ string $class; /** @var \PhpParser\Node\Arg[] */ - public /* readonly */ array $args; + private /* readonly */ array $args; /** @param \PhpParser\Node\Arg[] $args */ public function __construct(string $class, array $args) { @@ -3234,13 +3234,13 @@ class ClassInfo { public int $flags; public string $type; public /* readonly */ ?string $alias; - public /* readonly */ ?SimpleType $enumBackingType; - public /* readonly */ bool $isDeprecated; - public bool $isStrictProperties; + private /* readonly */ ?SimpleType $enumBackingType; + private /* readonly */ bool $isDeprecated; + private bool $isStrictProperties; /** @var AttributeInfo[] */ public array $attributes; - public ?ExposedDocComment $exposedDocComment; - public bool $isNotSerializable; + private ?ExposedDocComment $exposedDocComment; + private bool $isNotSerializable; /** @var Name[] */ public /* readonly */ array $extends; /** @var Name[] */ @@ -3248,11 +3248,11 @@ class ClassInfo { /** @var ConstInfo[] */ public /* readonly */ array $constInfos; /** @var PropertyInfo[] */ - public /* readonly */ array $propertyInfos; + private /* readonly */ array $propertyInfos; /** @var FuncInfo[] */ public array $funcInfos; /** @var EnumCaseInfo[] */ - public /* readonly */ array $enumCaseInfos; + private /* readonly */ array $enumCaseInfos; public /* readonly */ ?string $cond; public ?int $phpVersionIdMinimumCompatibility; public /* readonly */ bool $isUndocumentable; From 2af71d726686253167598378b76e63915de047ae Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:27:21 -0800 Subject: [PATCH 112/503] gen_stub: add `FileInfo` constructor Move the logic from `parseStubFile()` to `FileInfo::__construct()`, and in the process inline and remove `FileInfo::setMinimumPhpVersionIdCompatibility()`. --- build/gen_stub.php | 67 ++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 1734c67744492..0b2a66cf3177e 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4050,6 +4050,36 @@ class FileInfo { public bool $legacyArginfoGeneration = false; private ?int $minimumPhpVersionIdCompatibility = null; + /** @param array $fileTags */ + public function __construct(array $fileTags) { + foreach ($fileTags as $tag) { + if ($tag->name === 'generate-function-entries') { + $this->generateFunctionEntries = true; + $this->declarationPrefix = $tag->value ? $tag->value . " " : ""; + } else if ($tag->name === 'generate-legacy-arginfo') { + if ($tag->value && !in_array((int) $tag->value, ALL_PHP_VERSION_IDS, true)) { + throw new Exception( + "Legacy PHP version must be one of: \"" . PHP_70_VERSION_ID . "\" (PHP 7.0), \"" . PHP_80_VERSION_ID . "\" (PHP 8.0), " . + "\"" . PHP_81_VERSION_ID . "\" (PHP 8.1), \"" . PHP_82_VERSION_ID . "\" (PHP 8.2), \"" . PHP_83_VERSION_ID . "\" (PHP 8.3), " . + "\"" . PHP_84_VERSION_ID . "\" (PHP 8.4), \"" . PHP_85_VERSION_ID . "\" (PHP 8.5), \"" . $tag->value . "\" provided" + ); + } + + $this->minimumPhpVersionIdCompatibility = ($tag->value ? (int) $tag->value : PHP_70_VERSION_ID); + } else if ($tag->name === 'generate-class-entries') { + $this->generateClassEntries = true; + $this->declarationPrefix = $tag->value ? $tag->value . " " : ""; + } else if ($tag->name === 'undocumentable') { + $this->isUndocumentable = true; + } + } + + // Generating class entries require generating function/method entries + if ($this->generateClassEntries && !$this->generateFunctionEntries) { + $this->generateFunctionEntries = true; + } + } + /** * @return iterable */ @@ -4101,10 +4131,6 @@ public function __clone() } } - public function setMinimumPhpVersionIdCompatibility(?int $minimumPhpVersionIdCompatibility) { - $this->minimumPhpVersionIdCompatibility = $minimumPhpVersionIdCompatibility; - } - public function getMinimumPhpVersionIdCompatibility(): ?int { // Non-legacy arginfo files are always PHP 8.0+ compatible if (!$this->legacyArginfoGeneration && @@ -4918,37 +4944,8 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { $stmts = $parser->parse($code); $nodeTraverser->traverse($stmts); - $fileInfo = new FileInfo; - $fileDocComments = getFileDocComments($stmts); - if ($fileDocComments !== []) { - $fileTags = parseDocComments($fileDocComments); - foreach ($fileTags as $tag) { - if ($tag->name === 'generate-function-entries') { - $fileInfo->generateFunctionEntries = true; - $fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : ""; - } else if ($tag->name === 'generate-legacy-arginfo') { - if ($tag->value && !in_array((int) $tag->value, ALL_PHP_VERSION_IDS, true)) { - throw new Exception( - "Legacy PHP version must be one of: \"" . PHP_70_VERSION_ID . "\" (PHP 7.0), \"" . PHP_80_VERSION_ID . "\" (PHP 8.0), " . - "\"" . PHP_81_VERSION_ID . "\" (PHP 8.1), \"" . PHP_82_VERSION_ID . "\" (PHP 8.2), \"" . PHP_83_VERSION_ID . "\" (PHP 8.3), " . - "\"" . PHP_84_VERSION_ID . "\" (PHP 8.4), \"" . PHP_85_VERSION_ID . "\" (PHP 8.5), \"" . $tag->value . "\" provided" - ); - } - - $fileInfo->setMinimumPhpVersionIdCompatibility($tag->value ? (int) $tag->value : PHP_70_VERSION_ID); - } else if ($tag->name === 'generate-class-entries') { - $fileInfo->generateClassEntries = true; - $fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : ""; - } else if ($tag->name === 'undocumentable') { - $fileInfo->isUndocumentable = true; - } - } - } - - // Generating class entries require generating function/method entries - if ($fileInfo->generateClassEntries && !$fileInfo->generateFunctionEntries) { - $fileInfo->generateFunctionEntries = true; - } + $fileTags = parseDocComments(getFileDocComments($stmts)); + $fileInfo = new FileInfo($fileTags); handleStatements($fileInfo, $stmts, $prettyPrinter); return $fileInfo; From 2490cb67a2636eb05c366609ebc0b202e3fb3db3 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:30:00 -0800 Subject: [PATCH 113/503] gen_stub: remove `FuncInfo::getFramelessDeclaration()` parameter Unused, only caller passes in the same FuncInfo object that the method is called on. --- build/gen_stub.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 0b2a66cf3177e..70178583110e0 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1308,7 +1308,7 @@ public function getDeclaration(): ?string return $name->getDeclaration(); } - public function getFramelessDeclaration(FuncInfo $funcInfo): ?string { + public function getFramelessDeclaration(): ?string { if (empty($this->framelessFunctionInfos)) { return null; } @@ -5169,7 +5169,7 @@ static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { $framelessFunctionCode = generateCodeWithConditions( $fileInfo->getAllFuncInfos(), "\n", static function (FuncInfo $funcInfo) { - return $funcInfo->getFramelessDeclaration($funcInfo); + return $funcInfo->getFramelessDeclaration(); } ); From cecbcd9f3f88dd025354f8c418473713108ef9cb Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:33:31 -0800 Subject: [PATCH 114/503] gen_stub: add `reportFilePutContents()` helper Deduplicate reporting out each time a file is saved --- build/gen_stub.php | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 70178583110e0..5349adb1bf6f3 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -36,6 +36,13 @@ PHP_85_VERSION_ID, ]; +// file_put_contents() but with a success message printed after saving +function reportFilePutContents(string $filename, string $content): void { + if (file_put_contents($filename, $content)) { + echo "Saved $filename\n"; + } +} + /** * @return FileInfo[] */ @@ -121,8 +128,8 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = $context->allConstInfos, $stubHash ); - if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($arginfoFile, $arginfoCode)) { - echo "Saved $arginfoFile\n"; + if ($context->forceRegeneration || $stubHash !== $oldStubHash) { + reportFilePutContents($arginfoFile, $arginfoCode); } if ($fileInfo->shouldGenerateLegacyArginfo()) { @@ -146,8 +153,8 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = $context->allConstInfos, $stubHash ); - if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($legacyFile, $arginfoCode)) { - echo "Saved $legacyFile\n"; + if ($context->forceRegeneration || $stubHash !== $oldStubHash) { + reportFilePutContents($legacyFile, $arginfoCode); } } @@ -6290,9 +6297,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($replacePredefinedConstants) { foreach ($predefinedConstants as $filename => $content) { - if (file_put_contents($filename, $content)) { - echo "Saved $filename\n"; - } + reportFilePutContents($filename, $content); } } } @@ -6307,9 +6312,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } foreach ($classSynopses as $filename => $content) { - if (file_put_contents("$classSynopsesDirectory/$filename", $content)) { - echo "Saved $filename\n"; - } + reportFilePutContents("$classSynopsesDirectory/$filename", $content); } } } @@ -6319,9 +6322,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($replaceClassSynopses) { foreach ($classSynopses as $filename => $content) { - if (file_put_contents($filename, $content)) { - echo "Saved $filename\n"; - } + reportFilePutContents($filename, $content); } } } @@ -6340,9 +6341,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc mkdir(dirname($path)); } - if (file_put_contents($path, $content)) { - echo "Saved $filename\n"; - } + reportFilePutContents($path, $content); } } } @@ -6352,9 +6351,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($replaceMethodSynopses) { foreach ($methodSynopses as $filename => $content) { - if (file_put_contents($filename, $content)) { - echo "Saved $filename\n"; - } + reportFilePutContents($filename, $content); } } } @@ -6363,9 +6360,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc $filename = dirname(__FILE__, 2) . "/Zend/Optimizer/zend_func_infos.h"; $optimizerInfo = generateOptimizerInfo($funcMap); - if (file_put_contents($filename, $optimizerInfo)) { - echo "Saved $filename\n"; - } + reportFilePutContents($filename, $optimizerInfo); } if ($verifyManual) { From 8485a804ababe4bec3572b0d0384a6187025ffe6 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:36:39 -0800 Subject: [PATCH 115/503] gen_stub: stop cloning `Type` objects They are immutable --- build/gen_stub.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 5349adb1bf6f3..5143715179c00 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -531,6 +531,8 @@ public function equals(SimpleType $other): bool { } } +// Instances of Type are immutable and do not need to be cloned +// when held by an object that is cloned class Type { /** @var SimpleType[] */ public /* readonly */ array $types; @@ -3146,13 +3148,6 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie $fieldsynopsisElement->appendChild($doc->createElement("modifier", "readonly")); } } - - public function __clone() - { - if ($this->type) { - $this->type = clone $this->type; - } - } } class EnumCaseInfo { From d154603074e0afe1f261de1ad2f8f0c81cc6b50e Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:49:12 -0800 Subject: [PATCH 116/503] gen_stub: move `createExposedDocComment()` into `ExposedDocComment` Reduce the number of global functions by moving it to `ExposedDocComment::extractExposedComment()` --- build/gen_stub.php | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 5143715179c00..0680222d2a4da 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4224,6 +4224,29 @@ public function escape(): string { public function getLength(): int { return strlen($this->docComment); } + + /** @param array $comments */ + public static function extractExposedComment(array $comments): ?ExposedDocComment { + $exposedDocComment = null; + + foreach ($comments as $comment) { + $text = $comment->getText(); + $matches = []; + $pattern = "#^(\s*\/\*\*)(\s*@genstubs-expose-comment-block)(\s*)$#m"; + + if (preg_match($pattern, $text, $matches) !== 1) { + continue; + } + + if ($exposedDocComment !== null) { + throw new Exception("Only one PHPDoc comment block can be exposed"); + } + + $exposedDocComment = preg_replace($pattern, '$1$3', $text); + } + + return $exposedDocComment ? new ExposedDocComment($exposedDocComment) : null; + } } /** @return DocCommentTag[] */ @@ -4451,7 +4474,7 @@ function parseFunctionLike( $minimumPhpVersionIdCompatibility, createAttributes($func->attrGroups), $framelessFunctionInfos, - createExposedDocComment($comments) + ExposedDocComment::extractExposedComment($comments) ); } catch (Exception $e) { throw new Exception($name . "(): " .$e->getMessage()); @@ -4528,7 +4551,7 @@ function parseConstLike( $link, $phpVersionIdMinimumCompatibility, $attributes, - createExposedDocComment($comments), + ExposedDocComment::extractExposedComment($comments), $isFileCacheAllowed ); } @@ -4595,7 +4618,7 @@ function parseProperty( $link, $phpVersionIdMinimumCompatibility, $attributes, - createExposedDocComment($comments) + ExposedDocComment::extractExposedComment($comments) ); } @@ -4690,7 +4713,7 @@ function parseClass( $isDeprecated, $isStrictProperties, $attributes, - createExposedDocComment($comments), + ExposedDocComment::extractExposedComment($comments), $isNotSerializable, $extends, $implements, @@ -4720,29 +4743,6 @@ function createAttributes(array $attributeGroups): array { return $attributes; } -/** @param array $comments */ -function createExposedDocComment(array $comments): ?ExposedDocComment { - $exposedDocComment = null; - - foreach ($comments as $comment) { - $text = $comment->getText(); - $matches = []; - $pattern = "#^(\s*\/\*\*)(\s*@genstubs-expose-comment-block)(\s*)$#m"; - - if (preg_match($pattern, $text, $matches) !== 1) { - continue; - } - - if ($exposedDocComment !== null) { - throw new Exception("Only one PHPDoc comment block can be exposed"); - } - - $exposedDocComment = preg_replace($pattern, '$1$3', $text); - } - - return $exposedDocComment ? new ExposedDocComment($exposedDocComment) : null; -} - function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string { foreach ($stmt->getComments() as $comment) { $text = trim($comment->getText()); From 2d185e42ec6eebab6ab26d1bd280f854ad7b6c10 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 17:56:17 -0800 Subject: [PATCH 117/503] gen_stub: merge `parseDocComment()` into `parseDocComments()` Reduce the number of global functions merging `parseDocComment()` into its only caller --- build/gen_stub.php | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 0680222d2a4da..040828f87567e 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4253,22 +4253,15 @@ public static function extractExposedComment(array $comments): ?ExposedDocCommen function parseDocComments(array $comments): array { $tags = []; foreach ($comments as $comment) { - if ($comment instanceof DocComment) { - $tags = array_merge($tags, parseDocComment($comment)); + if (!($comment instanceof DocComment)) { + continue; } - } - - return $tags; -} - -/** @return DocCommentTag[] */ -function parseDocComment(DocComment $comment): array { - $commentText = substr($comment->getText(), 2, -2); - $tags = []; - foreach (explode("\n", $commentText) as $commentLine) { - $regex = '/^\*\s*@([a-z-]+)(?:\s+(.+))?$/'; - if (preg_match($regex, trim($commentLine), $matches)) { - $tags[] = new DocCommentTag($matches[1], $matches[2] ?? null); + $commentText = substr($comment->getText(), 2, -2); + foreach (explode("\n", $commentText) as $commentLine) { + $regex = '/^\*\s*@([a-z-]+)(?:\s+(.+))?$/'; + if (preg_match($regex, trim($commentLine), $matches)) { + $tags[] = new DocCommentTag($matches[1], $matches[2] ?? null); + } } } From 6d2c1edc76c4db8e7f84a132c73780fded94552b Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 18:02:21 -0800 Subject: [PATCH 118/503] gen_stub: move `createAttributes()` into `AttributeInfo` Reduce the number of global functions by moving it to `AttributeInfo::createFromGroups()`. In the process, fix the documentation for the return type, the result is an array of `AttributeInfo` objects, not `Attribute` objects. --- build/gen_stub.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 040828f87567e..93580d984df04 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -3229,6 +3229,22 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC } return $code; } + + /** + * @param array> $attributeGroups + * @return AttributeInfo[] + */ + public static function createFromGroups(array $attributeGroups): array { + $attributes = []; + + foreach ($attributeGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); + } + } + + return $attributes; + } } class ClassInfo { @@ -4426,7 +4442,7 @@ function parseFunctionLike( $type, isset($docParamTypes[$varName]) ? Type::fromString($docParamTypes[$varName]) : null, $param->default ? $prettyPrinter->prettyPrintExpr($param->default) : null, - createAttributes($param->attrGroups) + AttributeInfo::createFromGroups($param->attrGroups) ); if (!$param->default && !$param->variadic) { $numRequiredArgs = $i + 1; @@ -4465,7 +4481,7 @@ function parseFunctionLike( $cond, $isUndocumentable, $minimumPhpVersionIdCompatibility, - createAttributes($func->attrGroups), + AttributeInfo::createFromGroups($func->attrGroups), $framelessFunctionInfos, ExposedDocComment::extractExposedComment($comments) ); @@ -4656,7 +4672,7 @@ function parseClass( } } - $attributes = createAttributes($class->attrGroups); + $attributes = AttributeInfo::createFromGroups($class->attrGroups); foreach ($attributes as $attribute) { switch ($attribute->class) { case 'AllowDynamicProperties': @@ -4720,22 +4736,6 @@ function parseClass( ); } -/** - * @param array> $attributeGroups - * @return Attribute[] - */ -function createAttributes(array $attributeGroups): array { - $attributes = []; - - foreach ($attributeGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attr) { - $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); - } - } - - return $attributes; -} - function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string { foreach ($stmt->getComments() as $comment) { $text = trim($comment->getText()); @@ -4855,7 +4855,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $cond, $fileInfo->isUndocumentable, $fileInfo->getMinimumPhpVersionIdCompatibility(), - createAttributes($classStmt->attrGroups) + AttributeInfo::createFromGroups($classStmt->attrGroups) ); } } else if ($classStmt instanceof Stmt\Property) { @@ -4872,7 +4872,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $classStmt->getComments(), $prettyPrinter, $fileInfo->getMinimumPhpVersionIdCompatibility(), - createAttributes($classStmt->attrGroups) + AttributeInfo::createFromGroups($classStmt->attrGroups) ); } } else if ($classStmt instanceof Stmt\ClassMethod) { From 3177180af28cf5dea4fc6d326e22383abd59e761 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 18:07:11 -0800 Subject: [PATCH 119/503] gen_stub: simplify `getFileDocComments()` with `array_filter` --- build/gen_stub.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 93580d984df04..889e6df9c57c0 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4770,16 +4770,10 @@ function getFileDocComments(array $stmts): array { return []; } - $comments = $stmts[0]->getComments(); - - $result = []; - foreach ($comments as $comment) { - if ($comment instanceof DocComment) { - $result[] = $comment; - } - } - - return $result; + return array_filter( + $stmts[0]->getComments(), + static fn ( $comment ): bool => $comment instanceof DocComment + ); } function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstract $prettyPrinter) { From 81ef122ca97035fee722441fc20151fd55cf9d0e Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 21 Feb 2025 18:17:05 -0800 Subject: [PATCH 120/503] gen_stub: move `findEquivalentFuncInfo()` into `FuncInfo` Reduce the number of global functions by moving it to instance method `FuncInfo::findEquivalent()`. --- build/gen_stub.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 889e6df9c57c0..f8e16064ee292 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2088,6 +2088,16 @@ public function getMethodSynopsisElement(array $funcMap, array $aliasMap, DOMDoc return $methodSynopsis; } + /** @param FuncInfo[] $generatedFuncInfos */ + public function findEquivalent(array $generatedFuncInfos): ?FuncInfo { + foreach ($generatedFuncInfos as $generatedFuncInfo) { + if ($generatedFuncInfo->equalsApartFromNameAndRefcount($this)) { + return $generatedFuncInfo; + } + } + return null; + } + public function __clone() { foreach ($this->args as $key => $argInfo) { @@ -5053,16 +5063,6 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { return $code . "\n"; } -/** @param FuncInfo[] $generatedFuncInfos */ -function findEquivalentFuncInfo(array $generatedFuncInfos, FuncInfo $funcInfo): ?FuncInfo { - foreach ($generatedFuncInfos as $generatedFuncInfo) { - if ($generatedFuncInfo->equalsApartFromNameAndRefcount($funcInfo)) { - return $generatedFuncInfo; - } - } - return null; -} - /** * @template T * @param iterable $infos @@ -5136,7 +5136,7 @@ function generateArgInfoCode( $fileInfo->getAllFuncInfos(), "\n", static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { /* If there already is an equivalent arginfo structure, only emit a #define */ - if ($generatedFuncInfo = findEquivalentFuncInfo($generatedFuncInfos, $funcInfo)) { + if ($generatedFuncInfo = $funcInfo->findEquivalent($generatedFuncInfos)) { $code = sprintf( "#define %s %s\n", $funcInfo->getArgInfoName(), $generatedFuncInfo->getArgInfoName() From 69625406620c5dd565b3cdd1cdafb30d32029428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 17 Mar 2025 13:55:24 +0100 Subject: [PATCH 121/503] =?UTF-8?q?zend=5Fget=5Fcallable=5Fname:=20Return?= =?UTF-8?q?=20underlying=20callable=E2=80=99s=20name=20for=20fake=20closur?= =?UTF-8?q?es=20(#18063)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes php/php-src#18062 --- NEWS | 2 ++ UPGRADING.INTERNALS | 2 ++ Zend/tests/first_class_callable/gh18062.phpt | 32 ++++++++++++++++++++ Zend/zend_API.c | 13 ++++++++ 4 files changed, 49 insertions(+) create mode 100644 Zend/tests/first_class_callable/gh18062.phpt diff --git a/NEWS b/NEWS index e498fac1d82ef..48e71a0a80632 100644 --- a/NEWS +++ b/NEWS @@ -169,6 +169,8 @@ PHP NEWS - Standard: . Fixed crypt() tests on musl when using --with-external-libcrypt (Michael Orlitzky). + . Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first + class callables returns wrong name). (timwolla) - Streams: . Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows). diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index b963ead5cc8da..d2ab4e13fc52c 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -19,6 +19,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES a value to a non-reference zval. . Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor could interfere. + . zend_get_callable_name() now returns the name of the underlying function + for fake closures. ======================== 2. Build system changes diff --git a/Zend/tests/first_class_callable/gh18062.phpt b/Zend/tests/first_class_callable/gh18062.phpt new file mode 100644 index 0000000000000..3865dd77adba8 --- /dev/null +++ b/Zend/tests/first_class_callable/gh18062.phpt @@ -0,0 +1,32 @@ +--TEST-- +First Class Callable returns correct name from is_callable() +--FILE-- + +--EXPECT-- +string(9) "some_func" +string(13) "Foo::__invoke" +string(8) "Foo::bar" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 162f9aced147b..2be3d428270f2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4134,6 +4134,19 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj case IS_OBJECT: { zend_class_entry *ce = Z_OBJCE_P(callable); + + if (ce == zend_ce_closure) { + const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable)); + + if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + if (fn->common.scope) { + return zend_create_member_string(fn->common.scope->name, fn->common.function_name); + } else { + return zend_string_copy(fn->common.function_name); + } + } + } + return zend_string_concat2( ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke") - 1); From bd7d3c38ad2e7f67e24014fc5651471ce29487a7 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 17 Mar 2025 14:49:22 +0100 Subject: [PATCH 122/503] Get rid of atime change testing in bug72666_variation3.phpt --- ext/standard/tests/file/bug72666_variation3.phpt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ext/standard/tests/file/bug72666_variation3.phpt b/ext/standard/tests/file/bug72666_variation3.phpt index a491640c4f746..7937bd904ad7d 100644 --- a/ext/standard/tests/file/bug72666_variation3.phpt +++ b/ext/standard/tests/file/bug72666_variation3.phpt @@ -5,23 +5,11 @@ Bug #72666 (stat cache clearing inconsistent - plain wrapper) $filename = __DIR__ . '/bug72666_variation3.txt'; file_put_contents($filename, "test"); -$fd = fopen($filename, "r"); -$atime1 = fileatime($filename); -sleep(1); -var_dump(fread($fd, 4)); -$atime2 = fileatime($filename); $mtime1 = filemtime($filename); -fclose($fd); $fd = fopen($filename, "w"); sleep(1); var_dump(fwrite($fd, "data")); $mtime2 = filemtime($filename); -if (substr(PHP_OS, 0, 3) == 'WIN') { - // Windows do not hundle atime - var_dump($atime2 == $atime1); -} else { - var_dump($atime2 > $atime1); -} var_dump($mtime2 > $mtime1); ?> --CLEAN-- @@ -29,7 +17,5 @@ var_dump($mtime2 > $mtime1); unlink(__DIR__ . '/bug72666_variation3.txt'); ?> --EXPECT-- -string(4) "test" int(4) bool(true) -bool(true) From c531f3d79b1ddbddc04fe3a5b5f51e8d9c2f36d4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sat, 15 Mar 2025 12:18:08 +0100 Subject: [PATCH 123/503] Disable ZEND_RC_MOD_CHECK() while loading shared extension in FPM This fixes a ZEND_RC_MOD_CHECK() assertion failure when building with "-DZEND_RC_DEBUG=1 --enable-debug --enable-zts". php_dl() is called after startup, and manipulates the refcount of persistent strings, which is not allowed at this point of the lifecycle. The dl() function disables the ZEND_RC_MOD_CHECK() assertion before calling php_dl(). This change applies the same workaround in FPM. Closes GH-18075 --- sapi/fpm/fpm/fpm_php.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index b88c47671a1ec..2463f4351b605 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -93,7 +93,21 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ if (!strcmp(name, "extension") && *value) { zval zv; zend_interned_strings_switch_storage(0); + +#if ZEND_RC_DEBUG + bool orig_rc_debug = zend_rc_debug; + /* Loading extensions after php_module_startup() breaks some invariants. + * For instance, it will update the refcount of persistent strings, + * which is normally not allowed at this stage. */ + zend_rc_debug = false; +#endif + php_dl(value, MODULE_PERSISTENT, &zv, 1); + +#if ZEND_RC_DEBUG + zend_rc_debug = orig_rc_debug; +#endif + zend_interned_strings_switch_storage(1); return Z_TYPE(zv) == IS_TRUE ? FPM_PHP_INI_EXTENSION_LOADED : FPM_PHP_INI_EXTENSION_FAILED; } From 86a67fef482e0b6b54885ffe08696b3c061ec831 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 15 Mar 2025 01:38:27 +0100 Subject: [PATCH 124/503] Fix GH-12231: SimpleXML xpath should warn when returning other return types than node lists Closes GH-18073. --- NEWS | 4 ++++ UPGRADING | 5 +++++ ext/simplexml/simplexml.c | 22 ++++++++++++++++++++++ ext/simplexml/tests/008.phpt | 7 ++++--- ext/simplexml/tests/gh12231.phpt | 26 ++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 ext/simplexml/tests/gh12231.phpt diff --git a/NEWS b/NEWS index 48e71a0a80632..e2c67a4a24d12 100644 --- a/NEWS +++ b/NEWS @@ -124,6 +124,10 @@ PHP NEWS or a TypeError if read_and_close value is not compatible with int. (David Carlier) +- SimpleXML: + . Fixed bug GH-12231 (SimpleXML xpath should warn when returning other return + types than node lists). (nielsdos) + - SNMP: . snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3 and SNMP::__construct() throw an exception on invalid hostname, community diff --git a/UPGRADING b/UPGRADING index 11cca55bd1735..274f45d8f401b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -82,6 +82,11 @@ PHP 8.5 UPGRADE NOTES . A ValueError is now thrown when trying to set a cursor name that is too long on a PDOStatement resulting from the Firebird driver. +- SimpleXML: + - Passing an XPath expression that returns something other than a node set + to SimpleXMLElement::xpath() will now emit a warning and return false, + instead of silently failing and returning an empty array. + - SPL: . ArrayObject no longer accepts enums, as modifying the $name or $value properties can break engine assumptions. diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 1de7ccc6e74e8..877280fb378dc 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1215,6 +1215,21 @@ static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */ } /* }}} */ +static const char *sxe_get_object_type_name(xmlXPathObjectType type) +{ + switch (type) { + case XPATH_BOOLEAN: return "bool"; + case XPATH_NUMBER: return "number"; + case XPATH_STRING: return "string"; +#ifdef LIBXML_XPTR_LOCS_ENABLED + case XPATH_POINT: return "point"; + case XPATH_RANGE: return "range"; + case XPATH_LOCATIONSET: return "location set"; +#endif + default: return "undefined"; + } +} + /* {{{ Runs XPath query on the XML data */ PHP_METHOD(SimpleXMLElement, xpath) { @@ -1271,6 +1286,13 @@ PHP_METHOD(SimpleXMLElement, xpath) RETURN_FALSE; } + if (UNEXPECTED(retval->type != XPATH_NODESET)) { + php_error_docref(NULL, E_WARNING, "XPath expression must return a node set, %s returned", + sxe_get_object_type_name(retval->type)); + xmlXPathFreeObject(retval); + RETURN_FALSE; + } + result = retval->nodesetval; if (result != NULL) { diff --git a/ext/simplexml/tests/008.phpt b/ext/simplexml/tests/008.phpt index c946c36dafe63..dea6f98eacfcc 100644 --- a/ext/simplexml/tests/008.phpt +++ b/ext/simplexml/tests/008.phpt @@ -39,8 +39,9 @@ array(1) { } } } -array(0) { -} -Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d%A +Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d +bool(false) + +Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d bool(false) diff --git a/ext/simplexml/tests/gh12231.phpt b/ext/simplexml/tests/gh12231.phpt new file mode 100644 index 0000000000000..efacd92b76f95 --- /dev/null +++ b/ext/simplexml/tests/gh12231.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-12231 (SimpleXML xpath should warn when returning other return types than node lists) +--EXTENSIONS-- +simplexml +--FILE-- +"; +$sxe = simplexml_load_string($xml); + +var_dump($sxe->xpath("count(//foo)")); +var_dump($sxe->xpath("string(//foo)")); +var_dump($sxe->xpath("boolean(//foo)")); +var_dump(count($sxe->xpath("//foo"))); + +?> +--EXPECTF-- +Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d +bool(false) + +Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, string returned in %s on line %d +bool(false) + +Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, bool returned in %s on line %d +bool(false) +int(2) From 647baec5a4d3525033b05da48c5ed4ad51601d70 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 16 Mar 2025 13:40:54 +0100 Subject: [PATCH 125/503] Fix GH-18090: DOM: Svg attributes and tag names are being lowercased Closes GH-18091. --- NEWS | 2 ++ ext/dom/html5_parser.c | 12 ++++++++++-- ext/dom/tests/modern/html/parser/gh18090.phpt | 18 ++++++++++++++++++ .../html/parser/predefined_namespaces.phpt | 6 +++--- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 ext/dom/tests/modern/html/parser/gh18090.phpt diff --git a/NEWS b/NEWS index 286d03d10aff8..e7e917c6273da 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,8 @@ PHP NEWS - DOM: . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos) . Fix weird unpack behaviour in DOM. (nielsdos) + . Fixed bug GH-18090 (DOM: Svg attributes and tag names are being lowercased). + (nielsdos) - Fuzzer: . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI). diff --git a/ext/dom/html5_parser.c b/ext/dom/html5_parser.c index 0d7d2b9e7249d..f1dc2db53b25b 100644 --- a/ext/dom/html5_parser.c +++ b/ext/dom/html5_parser.c @@ -138,7 +138,9 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert( * If a prefix:name format is used, then the local name will be "prefix:name" and the prefix will be empty. * There is however still somewhat of a concept of namespaces. There are three: HTML (the default), SVG, and MATHML. */ lxb_dom_element_t *element = lxb_dom_interface_element(node); - const lxb_char_t *name = lxb_dom_element_local_name(element, NULL); + const lxb_char_t *name = lxb_dom_element_qualified_name(element, NULL); + ZEND_ASSERT(!element->node.prefix); + xmlNodePtr lxml_element = xmlNewDocNode(lxml_doc, NULL, name, NULL); if (UNEXPECTED(lxml_element == NULL)) { retval = LEXBOR_LIBXML2_BRIDGE_STATUS_OOM; @@ -203,7 +205,13 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert( for (lxb_dom_attr_t *attr = element->first_attr; attr != NULL; attr = attr->next) { /* Same namespace remark as for elements */ size_t local_name_length, value_length; - const lxb_char_t *local_name = lxb_dom_attr_local_name(attr, &local_name_length); + const lxb_char_t *local_name = lxb_dom_attr_qualified_name(attr, &local_name_length); + if (attr->node.prefix) { + const char *pos = strchr((const char *) local_name, ':'); + if (EXPECTED(pos)) { + local_name = (const lxb_char_t *) pos + 1; + } + } const lxb_char_t *value = lxb_dom_attr_value(attr, &value_length); if (UNEXPECTED(local_name_length >= INT_MAX || value_length >= INT_MAX)) { diff --git a/ext/dom/tests/modern/html/parser/gh18090.phpt b/ext/dom/tests/modern/html/parser/gh18090.phpt new file mode 100644 index 0000000000000..c32f5ddb51336 --- /dev/null +++ b/ext/dom/tests/modern/html/parser/gh18090.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-18090 (Svg attributes and tag names are being lowercased) +--EXTENSIONS-- +dom +--FILE-- +', LIBXML_NOERROR)->saveHTML(), "\n"; + +echo \Dom\HTMLDocument::createFromString('', LIBXML_NOERROR)->saveHTML(), "\n"; + +echo \Dom\HTMLDocument::createFromString('', LIBXML_NOERROR)->querySelector('svg')->attributes[0]->name, "\n"; +?> +--EXPECT-- + + +viewBox diff --git a/ext/dom/tests/modern/html/parser/predefined_namespaces.phpt b/ext/dom/tests/modern/html/parser/predefined_namespaces.phpt index 7e78460454e60..b4c07c6fb3bb8 100644 --- a/ext/dom/tests/modern/html/parser/predefined_namespaces.phpt +++ b/ext/dom/tests/modern/html/parser/predefined_namespaces.phpt @@ -47,7 +47,7 @@ echo $dom->saveXml(); svg http://www.w3.org/2000/svg Attribute: width (NONE) Attribute: height (NONE) - Attribute: viewbox (NONE) + Attribute: viewBox (NONE) rect http://www.w3.org/2000/svg Attribute: id (NONE) Attribute: x (NONE) @@ -65,7 +65,7 @@ svg http://www.w3.org/1998/Math/MathML Test - + @@ -85,7 +85,7 @@ svg http://www.w3.org/1998/Math/MathML Test - + From 25f451091487de812f97ed080c4a606e0fc0a616 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 17 Mar 2025 20:11:39 +0100 Subject: [PATCH 126/503] Merge JMP_FRAMELESS cache slots in Optimizer/compact_literals (#18093) This avoids repeated lookups in the function table for the same function name. Although this optimization is observable, i.e. defining a function via an include in between 2 JMP_FRAMELESS for the same function, this cannot be relied on already as far as I know if the optimizer runs. --- Zend/Optimizer/compact_literals.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index 4b27aebc9d39a..db973572aca3a 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -165,7 +165,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx HashTable hash; zend_string *key = NULL; void *checkpoint = zend_arena_checkpoint(ctx->arena); - int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot; + int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot, *jmp_slot; if (op_array->last_literal) { info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info)); @@ -175,6 +175,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx end = opline + op_array->last; while (opline < end) { switch (opline->opcode) { + case ZEND_JMP_FRAMELESS: + LITERAL_INFO(opline->op1.constant, 1); + break; case ZEND_INIT_FCALL_BY_NAME: LITERAL_INFO(opline->op2.constant, 2); break; @@ -480,13 +483,14 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx zend_hash_clean(&hash); op_array->last_literal = j; - const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int)); - memset(const_slot, -1, j * 6 * sizeof(int)); + const_slot = zend_arena_alloc(&ctx->arena, j * 7 * sizeof(int)); + memset(const_slot, -1, j * 7 * sizeof(int)); class_slot = const_slot + j; func_slot = class_slot + j; bind_var_slot = func_slot + j; property_slot = bind_var_slot + j; method_slot = property_slot + j; + jmp_slot = method_slot + j; /* Update opcodes to use new literals table */ cache_size = zend_op_array_extension_handles * sizeof(void*); @@ -773,10 +777,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_CLASS_DELAYED: - case ZEND_JMP_FRAMELESS: opline->extended_value = cache_size; cache_size += sizeof(void *); break; + case ZEND_JMP_FRAMELESS: + // op1 func + if (jmp_slot[opline->op1.constant] >= 0) { + opline->extended_value = jmp_slot[opline->op1.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + jmp_slot[opline->op1.constant] = opline->extended_value; + } + break; case ZEND_SEND_VAL: case ZEND_SEND_VAL_EX: case ZEND_SEND_VAR: From 747851724efcdae1502040eec4787fa7b911b6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 17 Mar 2025 20:41:10 +0100 Subject: [PATCH 127/503] [skip ci] Update ext/random year for myself in EXTENSIONS --- EXTENSIONS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXTENSIONS b/EXTENSIONS index 6c3a83b8d9124..c389b052a8727 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -412,7 +412,7 @@ STATUS: Working ------------------------------------------------------------------------------- EXTENSION: random PRIMARY MAINTAINER Go Kudo (2022 - 2024) - Tim Düsterhus (2022 - 2024) + Tim Düsterhus (2022 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 8.2.0 From 56841998de9066857db4e773e17c3a1c28389701 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 14 Mar 2025 13:16:36 +0100 Subject: [PATCH 128/503] Fix IN_ARRAY optimization in_array() calls are compiled to frameless calls. Adjust the optimization appropriately. Luckily, frameless opcodes simplify the optimization quite a bit. Fixes GH-18050 Closes GH-18066 --- NEWS | 1 + Zend/Optimizer/dfa_pass.c | 92 +++++++--------------------------- ext/opcache/tests/gh18050.phpt | 67 +++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 74 deletions(-) create mode 100644 ext/opcache/tests/gh18050.phpt diff --git a/NEWS b/NEWS index e7e917c6273da..df641212d5f0e 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,7 @@ PHP NEWS JIT). (nielsdos) . Fixed bug GH-17966 (Symfony JIT 1205 assertion failure). (nielsdos) . Fixed bug GH-18037 (SEGV Zend/zend_execute.c). (nielsdos) + . Fixed bug GH-18050 (IN_ARRAY optimization in DFA pass is broken). (ilutov) - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index ce2a19f2e8fe9..2c3aaae065997 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -407,40 +407,28 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) zend_call_info *call_info = func_info->callee_info; do { - if (call_info->caller_call_opline - && call_info->caller_call_opline->opcode == ZEND_DO_ICALL + zend_op *op = call_info->caller_init_opline; + + if ((op->opcode == ZEND_FRAMELESS_ICALL_2 + || (op->opcode == ZEND_FRAMELESS_ICALL_3 && (op + 1)->op1_type == IS_CONST)) && call_info->callee_func - && zend_string_equals_literal(call_info->callee_func->common.function_name, "in_array") - && (call_info->caller_init_opline->extended_value == 2 - || (call_info->caller_init_opline->extended_value == 3 - && (call_info->caller_call_opline - 1)->opcode == ZEND_SEND_VAL - && (call_info->caller_call_opline - 1)->op1_type == IS_CONST))) { - - zend_op *send_array; - zend_op *send_needly; + && zend_string_equals_literal_ci(call_info->callee_func->common.function_name, "in_array")) { + bool strict = 0; + bool has_opdata = op->opcode == ZEND_FRAMELESS_ICALL_3; ZEND_ASSERT(!call_info->is_prototype); - if (call_info->caller_init_opline->extended_value == 2) { - send_array = call_info->caller_call_opline - 1; - send_needly = call_info->caller_call_opline - 2; - } else { - if (zend_is_true(CT_CONSTANT_EX(op_array, (call_info->caller_call_opline - 1)->op1.constant))) { + if (has_opdata) { + if (zend_is_true(CT_CONSTANT_EX(op_array, (op + 1)->op1.constant))) { strict = 1; } - send_array = call_info->caller_call_opline - 2; - send_needly = call_info->caller_call_opline - 3; } - if (send_array->opcode == ZEND_SEND_VAL - && send_array->op1_type == IS_CONST - && Z_TYPE_P(CT_CONSTANT_EX(op_array, send_array->op1.constant)) == IS_ARRAY - && (send_needly->opcode == ZEND_SEND_VAL - || send_needly->opcode == ZEND_SEND_VAR) - ) { + if (op->op2_type == IS_CONST + && Z_TYPE_P(CT_CONSTANT_EX(op_array, op->op2.constant)) == IS_ARRAY) { bool ok = 1; - HashTable *src = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, send_array->op1.constant)); + HashTable *src = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, op->op2.constant)); HashTable *dst; zval *val, tmp; zend_ulong idx; @@ -471,59 +459,15 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) } if (ok) { - uint32_t op_num = send_needly - op_array->opcodes; - zend_ssa_op *ssa_op = ssa->ops + op_num; - - if (ssa_op->op1_use >= 0) { - /* Reconstruct SSA */ - int var_num = ssa_op->op1_use; - zend_ssa_var *var = ssa->vars + var_num; - - ZEND_ASSERT(ssa_op->op1_def < 0); - zend_ssa_unlink_use_chain(ssa, op_num, ssa_op->op1_use); - ssa_op->op1_use = -1; - ssa_op->op1_use_chain = -1; - op_num = call_info->caller_call_opline - op_array->opcodes; - ssa_op = ssa->ops + op_num; - ssa_op->op1_use = var_num; - ssa_op->op1_use_chain = var->use_chain; - var->use_chain = op_num; - } - ZVAL_ARR(&tmp, dst); /* Update opcode */ - call_info->caller_call_opline->opcode = ZEND_IN_ARRAY; - call_info->caller_call_opline->extended_value = strict; - call_info->caller_call_opline->op1_type = send_needly->op1_type; - call_info->caller_call_opline->op1.num = send_needly->op1.num; - call_info->caller_call_opline->op2_type = IS_CONST; - call_info->caller_call_opline->op2.constant = zend_optimizer_add_literal(op_array, &tmp); - if (call_info->caller_init_opline->extended_value == 3) { - MAKE_NOP(call_info->caller_call_opline - 1); - } - MAKE_NOP(call_info->caller_init_opline); - MAKE_NOP(send_needly); - MAKE_NOP(send_array); - removed_ops++; - - op_num = call_info->caller_call_opline - op_array->opcodes; - ssa_op = ssa->ops + op_num; - if (ssa_op->result_def >= 0) { - int var = ssa_op->result_def; - int use = ssa->vars[var].use_chain; - - /* If the result is used only in a JMPZ/JMPNZ, replace result type with - * IS_TMP_VAR, which will enable use of smart branches. Don't do this - * in other cases, as not all opcodes support both VAR and TMP. */ - if (ssa->vars[var].phi_use_chain == NULL - && ssa->ops[use].op1_use == var - && ssa->ops[use].op1_use_chain == -1 - && (op_array->opcodes[use].opcode == ZEND_JMPZ - || op_array->opcodes[use].opcode == ZEND_JMPNZ)) { - call_info->caller_call_opline->result_type = IS_TMP_VAR; - op_array->opcodes[use].op1_type = IS_TMP_VAR; - } + op->opcode = ZEND_IN_ARRAY; + op->extended_value = strict; + op->op2.constant = zend_optimizer_add_literal(op_array, &tmp); + if (has_opdata) { + MAKE_NOP(op + 1); + removed_ops++; } } } diff --git a/ext/opcache/tests/gh18050.phpt b/ext/opcache/tests/gh18050.phpt new file mode 100644 index 0000000000000..3fb6c8d7b65ed --- /dev/null +++ b/ext/opcache/tests/gh18050.phpt @@ -0,0 +1,67 @@ +--TEST-- +GH-18050: Frameless calls break IN_ARRAY optimization +--EXTENSIONS-- +opcache +--INI-- +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=%d, args=%d, vars=%d, tmps=%d) + ; (after optimizer) + ; %sgh18050.php:%s +0000 INIT_FCALL 1 %d string("test") +0001 SEND_VAL string("x") 1 +0002 DO_UCALL +0003 INIT_FCALL 1 %d string("test") +0004 SEND_VAL string("z") 1 +0005 DO_UCALL +0006 RETURN int(1) + +test: + ; (lines=%d, args=%d, vars=%d, tmps=%d) + ; (after optimizer) + ; %sgh18050.php:%s +0000 CV0($v) = RECV 1 +0001 INIT_FCALL 1 %d string("var_dump") +0002 T1 = IN_ARRAY 0 CV0($v) array(...) +0003 SEND_VAL T1 1 +0004 DO_ICALL +0005 INIT_FCALL 1 %d string("var_dump") +0006 T1 = IN_ARRAY 0 CV0($v) array(...) +0007 SEND_VAL T1 1 +0008 DO_ICALL +0009 INIT_FCALL 1 %d string("var_dump") +0010 T1 = IN_ARRAY 1 CV0($v) array(...) +0011 SEND_VAL T1 1 +0012 DO_ICALL +0013 T1 = IN_ARRAY 1 CV0($v) array(...) +0014 JMPZ T1 0016 +0015 ECHO string("True +") +0016 RETURN null +bool(true) +bool(true) +bool(true) +True +bool(false) +bool(false) +bool(false) From 57efcb98545808254c60b1424366ca22ec22ede0 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 18 Mar 2025 14:22:14 +0100 Subject: [PATCH 129/503] Fix new opcache dump format in test expectation --- ext/opcache/tests/gh18050.phpt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/opcache/tests/gh18050.phpt b/ext/opcache/tests/gh18050.phpt index 3fb6c8d7b65ed..d71bc4c4d750f 100644 --- a/ext/opcache/tests/gh18050.phpt +++ b/ext/opcache/tests/gh18050.phpt @@ -55,8 +55,7 @@ test: 0012 DO_ICALL 0013 T1 = IN_ARRAY 1 CV0($v) array(...) 0014 JMPZ T1 0016 -0015 ECHO string("True -") +0015 ECHO string("True\n") 0016 RETURN null bool(true) bool(true) From 632924821708126a660a34bcd6f7be434a716304 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 18 Mar 2025 17:36:40 +0000 Subject: [PATCH 130/503] Zend/hash: Add yet more const qualifiers (#18084) --- Zend/zend_hash.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index d543dae2bab59..b2aaecce0d27c 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -261,7 +261,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(const HashTable * static zend_always_inline zend_result zend_hash_has_more_elements_ex(const HashTable *ht, const HashPosition *pos) { return (zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTENT ? FAILURE : SUCCESS); } -static zend_always_inline zend_result zend_hash_has_more_elements(HashTable *ht) { +static zend_always_inline zend_result zend_hash_has_more_elements(const HashTable *ht) { return zend_hash_has_more_elements_ex(ht, &ht->nInternalPointer); } static zend_always_inline zend_result zend_hash_move_forward(HashTable *ht) { @@ -554,7 +554,7 @@ static zend_always_inline zval *zend_symtable_find_ind(const HashTable *ht, zend } -static zend_always_inline bool zend_symtable_exists(HashTable *ht, zend_string *key) +static zend_always_inline bool zend_symtable_exists(const HashTable *ht, zend_string *key) { zend_ulong idx; @@ -566,7 +566,7 @@ static zend_always_inline bool zend_symtable_exists(HashTable *ht, zend_string * } -static zend_always_inline bool zend_symtable_exists_ind(HashTable *ht, zend_string *key) +static zend_always_inline bool zend_symtable_exists_ind(const HashTable *ht, zend_string *key) { zend_ulong idx; @@ -937,7 +937,7 @@ static zend_always_inline void *zend_hash_index_find_ptr(const HashTable *ht, ze } } -static zend_always_inline zval *zend_hash_index_find_deref(HashTable *ht, zend_ulong h) +static zend_always_inline zval *zend_hash_index_find_deref(const HashTable *ht, zend_ulong h) { zval *zv = zend_hash_index_find(ht, h); if (zv) { @@ -946,7 +946,7 @@ static zend_always_inline zval *zend_hash_index_find_deref(HashTable *ht, zend_u return zv; } -static zend_always_inline zval *zend_hash_find_deref(HashTable *ht, zend_string *str) +static zend_always_inline zval *zend_hash_find_deref(const HashTable *ht, zend_string *str) { zval *zv = zend_hash_find(ht, str); if (zv) { @@ -955,7 +955,7 @@ static zend_always_inline zval *zend_hash_find_deref(HashTable *ht, zend_string return zv; } -static zend_always_inline zval *zend_hash_str_find_deref(HashTable *ht, const char *str, size_t len) +static zend_always_inline zval *zend_hash_str_find_deref(const HashTable *ht, const char *str, size_t len) { zval *zv = zend_hash_str_find(ht, str, len); if (zv) { @@ -964,7 +964,7 @@ static zend_always_inline zval *zend_hash_str_find_deref(HashTable *ht, const ch return zv; } -static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, size_t len) +static zend_always_inline void *zend_symtable_str_find_ptr(const HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -975,7 +975,7 @@ static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const } } -static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPosition *pos) +static zend_always_inline void *zend_hash_get_current_data_ptr_ex(const HashTable *ht, const HashPosition *pos) { zval *zv; From d9329b15220ecc127cfce75d4fe1b6ca6fc6236d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 17 Mar 2025 20:05:43 +0100 Subject: [PATCH 131/503] Fix xinclude destruction of live attributes Follow-up for GH-17847 but now for attributes. Closes GH-18100. --- NEWS | 1 + ext/dom/document.c | 14 ++++++++++++++ ext/dom/tests/gh17847.phpt | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 59b66e85f84f9..46510db971ea7 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ PHP NEWS - DOM: . Fix weird unpack behaviour in DOM. (nielsdos) + . Fix xinclude destruction of live attributes. (nielsdos) - GD: . Fixed bug GH-17984 (calls with arguments as array with references). diff --git a/ext/dom/document.c b/ext/dom/document.c index 0388249766e1f..42d67d5739845 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1607,14 +1607,28 @@ static zend_always_inline xmlNodePtr php_dom_next_in_tree_order(const xmlNode *n } } +static void dom_xinclude_strip_references_for_attributes(xmlNodePtr basep) +{ + for (xmlAttrPtr prop = basep->properties; prop; prop = prop->next) { + php_libxml_node_free_resource((xmlNodePtr) prop); + for (xmlNodePtr child = prop->children; child; child = child->next) { + php_libxml_node_free_resource(child); + } + } +} + static void dom_xinclude_strip_references(xmlNodePtr basep) { php_libxml_node_free_resource(basep); + dom_xinclude_strip_references_for_attributes(basep); xmlNodePtr current = basep->children; while (current) { php_libxml_node_free_resource(current); + if (current->type == XML_ELEMENT_NODE) { + dom_xinclude_strip_references_for_attributes(current); + } current = php_dom_next_in_tree_order(current, basep); } } diff --git a/ext/dom/tests/gh17847.phpt b/ext/dom/tests/gh17847.phpt index 5d5df0b3be05f..01601ca035265 100644 --- a/ext/dom/tests/gh17847.phpt +++ b/ext/dom/tests/gh17847.phpt @@ -13,7 +13,7 @@ $doc->loadXML(<< -

garbage

+

garbage

@@ -22,15 +22,22 @@ XML); $xpath = new DOMXPath($doc); $garbage = []; -foreach ($xpath->query('//p') as $entry) +foreach ($xpath->query('//p') as $entry) { $garbage[] = $entry; + foreach ($entry->attributes as $attr) { + $garbage[] = $attr; + foreach ($attr->childNodes as $child) { + $garbage[] = $child; + } + } +} @$doc->xinclude(); var_dump($garbage); ?> --EXPECT-- -array(3) { +array(7) { [0]=> object(DOMElement)#3 (1) { ["schemaTypeInfo"]=> @@ -46,4 +53,24 @@ array(3) { ["schemaTypeInfo"]=> NULL } + [3]=> + object(DOMAttr)#10 (2) { + ["specified"]=> + bool(true) + ["schemaTypeInfo"]=> + NULL + } + [4]=> + object(DOMText)#13 (0) { + } + [5]=> + object(DOMAttr)#12 (2) { + ["specified"]=> + bool(true) + ["schemaTypeInfo"]=> + NULL + } + [6]=> + object(DOMText)#15 (0) { + } } From fb07c62f2cba5941f02a1b5b02580f3aa40c7c69 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Wed, 19 Mar 2025 18:10:12 +0900 Subject: [PATCH 132/503] ext/bcmath: Extracted common logic into function and macro (#18103) --- ext/bcmath/libbcmath/src/convert.h | 26 +++++++++++++++++++++++++ ext/bcmath/libbcmath/src/div.c | 23 ++++------------------ ext/bcmath/libbcmath/src/private.h | 2 ++ ext/bcmath/libbcmath/src/recmul.c | 31 ++++++------------------------ 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/ext/bcmath/libbcmath/src/convert.h b/ext/bcmath/libbcmath/src/convert.h index e278ae5fef1aa..73c38cd130107 100644 --- a/ext/bcmath/libbcmath/src/convert.h +++ b/ext/bcmath/libbcmath/src/convert.h @@ -85,4 +85,30 @@ static inline void bc_convert_to_vector_with_zero_pad(BC_VECTOR *n_vector, const bc_convert_to_vector(n_vector, nend, nlen); } +static inline void bc_convert_vector_to_char(const BC_VECTOR *vector, char *nptr, char *nend, size_t arr_size) +{ + size_t i = 0; + while (i < arr_size - 1) { +#if BC_VECTOR_SIZE == 4 + bc_write_bcd_representation(vector[i], nend - 3); + nend -= 4; +#else + bc_write_bcd_representation(vector[i] / 10000, nend - 7); + bc_write_bcd_representation(vector[i] % 10000, nend - 3); + nend -= 8; +#endif + i++; + } + + /* + * The last digit may carry over. + * Also need to fill it to the end with zeros, so loop until the end of the string. + */ + BC_VECTOR last = vector[i]; + while (nend >= nptr) { + *nend-- = last % BASE; + last /= BASE; + } +} + #endif diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 7da023df9a7e4..1cf8a434c8608 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -255,10 +255,10 @@ static void bc_do_div( const char *divisor, size_t divisor_size, bc_num *quot, size_t quot_size ) { - size_t numerator_arr_size = (numerator_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t divisor_arr_size = (divisor_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t numerator_arr_size = BC_ARR_SIZE_FROM_LEN(numerator_size); + size_t divisor_arr_size = BC_ARR_SIZE_FROM_LEN(divisor_size); size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1; - size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); + size_t quot_real_arr_size = MIN(quot_arr_size, BC_ARR_SIZE_FROM_LEN(quot_size)); BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; size_t allocation_arr_size = numerator_arr_size + divisor_arr_size + quot_arr_size; @@ -293,22 +293,7 @@ static void bc_do_div( char *qptr = (*quot)->n_value; char *qend = qptr + (*quot)->n_len + (*quot)->n_scale - 1; - size_t i; - for (i = 0; i < quot_real_arr_size - 1; i++) { -#if BC_VECTOR_SIZE == 4 - bc_write_bcd_representation(quot_vectors[i], qend - 3); - qend -= 4; -#else - bc_write_bcd_representation(quot_vectors[i] / 10000, qend - 7); - bc_write_bcd_representation(quot_vectors[i] % 10000, qend - 3); - qend -= 8; -#endif - } - - while (qend >= qptr) { - *qend-- = quot_vectors[i] % BASE; - quot_vectors[i] /= BASE; - } + bc_convert_vector_to_char(quot_vectors, qptr, qend, quot_real_arr_size); if (allocation_arr_size > BC_STACK_VECTOR_SIZE) { efree(numerator_vectors); diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 7e972952c75e3..91facfb2f8b40 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -67,6 +67,8 @@ /* 64-bytes for 64-bit */ #define BC_STACK_VECTOR_SIZE 8 +#define BC_ARR_SIZE_FROM_LEN(len) (((len) + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE) + /* * Adding more than this many times may cause uint32_t/uint64_t to overflow. * Typically this is 1844 for 64bit and 42 for 32bit. diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index fc7efb37ebf02..26ce1641db410 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -107,27 +107,8 @@ static inline void bc_mul_finish_from_vector(BC_VECTOR *prod_vector, size_t prod *prod = bc_new_num_nonzeroed(prodlen, 0); char *pptr = (*prod)->n_value; char *pend = pptr + prodlen - 1; - size_t i = 0; - while (i < prod_arr_size - 1) { -#if BC_VECTOR_SIZE == 4 - bc_write_bcd_representation(prod_vector[i], pend - 3); - pend -= 4; -#else - bc_write_bcd_representation(prod_vector[i] / 10000, pend - 7); - bc_write_bcd_representation(prod_vector[i] % 10000, pend - 3); - pend -= 8; -#endif - i++; - } - /* - * The last digit may carry over. - * Also need to fill it to the end with zeros, so loop until the end of the string. - */ - while (pend >= pptr) { - *pend-- = prod_vector[i] % BASE; - prod_vector[i] /= BASE; - } + bc_convert_vector_to_char(prod_vector, pptr, pend, prod_arr_size); } /* @@ -145,9 +126,9 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc const char *n2end = n2->n_value + n2len - 1; size_t prodlen = n1len + n2len; - size_t n1_arr_size = (n1len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t n2_arr_size = (n2len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t n1_arr_size = BC_ARR_SIZE_FROM_LEN(n1len); + size_t n2_arr_size = BC_ARR_SIZE_FROM_LEN(n2len); + size_t prod_arr_size = BC_ARR_SIZE_FROM_LEN(prodlen); BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; size_t allocation_arr_size = n1_arr_size + n2_arr_size + prod_arr_size; @@ -206,8 +187,8 @@ static void bc_standard_square(bc_num n1, size_t n1len, bc_num *prod) const char *n1end = n1->n_value + n1len - 1; size_t prodlen = n1len + n1len; - size_t n1_arr_size = (n1len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t n1_arr_size = BC_ARR_SIZE_FROM_LEN(n1len); + size_t prod_arr_size = BC_ARR_SIZE_FROM_LEN(prodlen); BC_VECTOR *buf = safe_emalloc(n1_arr_size + n1_arr_size + prod_arr_size, sizeof(BC_VECTOR), 0); From d5251513b1fd0745d2b1ac482b841ada001f1a3a Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 19 Mar 2025 21:56:00 +0000 Subject: [PATCH 133/503] ext/pgsql: get_field_name helper, remove unused precaution for pg_type request. (#18025) it is an internal table and oid is a real Oid (uint32_t) value. --- ext/pgsql/pgsql.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 036fc5c0572a1..3210409ba385f 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1670,8 +1670,7 @@ static zend_string *get_field_name(PGconn *pgsql, Oid oid) continue; } - char *end_ptr; - Oid tmp_oid = strtoul(tmp_oid_str, &end_ptr, 10); + Oid tmp_oid = strtoul(tmp_oid_str, NULL, 10); zend_string *name = zend_string_init(tmp_name, strlen(tmp_name), 0); zend_hash_index_update_ptr(&PGG(field_oids), tmp_oid, name); From b932c267f8dee61c298a5c3ad4c05fc26689f7ff Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 20 Mar 2025 01:10:56 +0300 Subject: [PATCH 134/503] Update IR IR commit: 3d0124a06ee4321e1305f893b74840033d939e88 --- ext/opcache/jit/ir/ir.c | 8 +++++ ext/opcache/jit/ir/ir_fold.h | 57 ++++++++++++++++++++++++++++++++++-- ext/opcache/jit/ir/ir_sccp.c | 6 +++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/ext/opcache/jit/ir/ir.c b/ext/opcache/jit/ir/ir.c index 2721de4a6e006..d9f7e3d0f7836 100644 --- a/ext/opcache/jit/ir/ir.c +++ b/ext/opcache/jit/ir/ir.c @@ -2413,10 +2413,18 @@ static ir_ref _ir_fold_condition(ir_ctx *ctx, ir_ref ref) if (IR_IS_TYPE_INT(op2_insn->type) && op2_insn->val.u64 == 0) { ref = insn->op1; insn = &ctx->ir_base[ref]; + if (insn->op == IR_ALLOCA || insn->op == IR_VADDR) { + return IR_TRUE; + } } } else if (insn->op == IR_EQ && insn->op2 == IR_TRUE) { ref = insn->op1; insn = &ctx->ir_base[ref]; + } else if (insn->op == IR_EQ && insn->op2 == IR_NULL) { + ir_insn *op1_insn = &ctx->ir_base[insn->op1]; + if (op1_insn->op == IR_ALLOCA || op1_insn->op == IR_VADDR) { + return IR_FALSE; + } } // while (insn->op == IR_SEXT || insn->op == IR_ZEXT || insn->op == IR_BITCAST) { // ref = insn->op1; diff --git a/ext/opcache/jit/ir/ir_fold.h b/ext/opcache/jit/ir/ir_fold.h index 6f0bfea47820d..c7745a8c68723 100644 --- a/ext/opcache/jit/ir/ir_fold.h +++ b/ext/opcache/jit/ir/ir_fold.h @@ -1464,7 +1464,9 @@ IR_FOLD(EQ(SEXT, C_I32)) IR_FOLD(EQ(SEXT, C_I64)) IR_FOLD(EQ(SEXT, C_ADDR)) { - if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { + if (ctx->use_lists && ctx->use_lists[op1_insn->op1].count != 1) { + /* pass */ + } else if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { opt = IR_OPT(IR_NOT, IR_BOOL); op1 = op1_insn->op1; op2 = IR_UNUSED; @@ -1509,7 +1511,9 @@ IR_FOLD(NE(SEXT, C_I32)) IR_FOLD(NE(SEXT, C_I64)) IR_FOLD(NE(SEXT, C_ADDR)) { - if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { + if (ctx->use_lists && ctx->use_lists[op1_insn->op1].count != 1) { + /* pass */ + } else if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { IR_FOLD_COPY(op1_insn->op1); } else { ir_type type = ctx->ir_base[op1_insn->op1].type; @@ -2464,6 +2468,17 @@ IR_FOLD(SEXT(AND)) IR_FOLD_NEXT; } +IR_FOLD(SEXT(SHR)) +{ + if (IR_IS_CONST_REF(op1_insn->op2) + && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op) + && ctx->ir_base[op1_insn->op2].val.u64 != 0) { + opt = IR_OPT(IR_ZEXT, IR_OPT_TYPE(opt)); + IR_FOLD_RESTART; + } + IR_FOLD_NEXT; +} + IR_FOLD(TRUNC(AND)) { if (IR_IS_CONST_REF(op1_insn->op2)) { @@ -2490,6 +2505,44 @@ IR_FOLD(TRUNC(AND)) IR_FOLD_NEXT; } +IR_FOLD(AND(ZEXT, C_I16)) +IR_FOLD(AND(ZEXT, C_U16)) +IR_FOLD(AND(ZEXT, C_I32)) +IR_FOLD(AND(ZEXT, C_U32)) +IR_FOLD(AND(ZEXT, C_I64)) +IR_FOLD(AND(ZEXT, C_U64)) +IR_FOLD(AND(ZEXT, C_ADDR)) +{ + ir_type src_size = ir_type_size[ctx->ir_base[op1_insn->op1].type]; + + if ((src_size == 1 && op2_insn->val.u64 == 0xff) + || (src_size == 2 && op2_insn->val.u64 == 0xffff) + || (src_size == 4 && op2_insn->val.u64 == 0xffffffff)) { + IR_FOLD_COPY(op1); + } + IR_FOLD_NEXT; +} + +IR_FOLD(AND(SEXT, C_I16)) +IR_FOLD(AND(SEXT, C_U16)) +IR_FOLD(AND(SEXT, C_I32)) +IR_FOLD(AND(SEXT, C_U32)) +IR_FOLD(AND(SEXT, C_I64)) +IR_FOLD(AND(SEXT, C_U64)) +IR_FOLD(AND(SEXT, C_ADDR)) +{ + ir_type src_size = ir_type_size[ctx->ir_base[op1_insn->op1].type]; + + if ((src_size == 1 && op2_insn->val.u64 == 0xff) + || (src_size == 2 && op2_insn->val.u64 == 0xffff) + || (src_size == 4 && op2_insn->val.u64 == 0xffffffff)) { + opt = IR_OPT(IR_ZEXT, IR_OPT_TYPE(opt)); + op1 = op1_insn->op1; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } + IR_FOLD_NEXT; +} IR_FOLD(AND(SHR, C_I8)) IR_FOLD(AND(SHR, C_U8)) { diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 42012f222f7ff..af039aaef829b 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -927,7 +927,7 @@ static bool ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_ref ref, ir_i IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN); old_merge_inputs = insn->inputs_count; new_merge_inputs = 0; - life_inputs = (old_merge_inputs - IR_BITSET_BITS) ? &holder : ir_bitset_malloc(old_merge_inputs + 1); + life_inputs = (old_merge_inputs < IR_BITSET_BITS) ? &holder : ir_bitset_malloc(old_merge_inputs + 1); for (i = 1; i <= old_merge_inputs; i++) { ir_ref input = ir_insn_op(insn, i); @@ -3328,6 +3328,10 @@ static ir_ref ir_iter_optimize_condition(ir_ctx *ctx, ir_ref control, ir_ref con condition_insn = &ctx->ir_base[condition]; } + if (condition_insn->op == IR_ALLOCA || condition_insn->op == IR_VADDR) { + return IR_TRUE; + } + if (!IR_IS_CONST_REF(condition) && ctx->use_lists[condition].count > 1) { condition = ir_check_dominating_predicates(ctx, control, condition); } From e1eeb483efa9c82f88fd0dedf40906940388d630 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:43:30 +0100 Subject: [PATCH 135/503] Fix GH-18114: pdo lazy object crash (#18116) Since 0537968, the properties are no longer initialized. So we call object_properties_init to handle that correctly. Lower branches have a memory leak, but that requires a separate fix. --- ext/pdo/pdo_stmt.c | 2 ++ ext/pdo_sqlite/tests/gh18114.phpt | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 ext/pdo_sqlite/tests/gh18114.phpt diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 0ffded87c08a0..58924b0dfae42 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -212,6 +212,7 @@ static void pdo_get_lazy_object(pdo_stmt_t *stmt, zval *return_value) /* {{{ */ pdo_row_t *row = zend_object_alloc(sizeof(pdo_row_t), pdo_row_ce); row->stmt = stmt; zend_object_std_init(&row->std, pdo_row_ce); + object_properties_init(&row->std, pdo_row_ce); stmt->lazy_object_ref = &row->std; GC_ADDREF(&stmt->std); GC_DELREF(&row->std); @@ -2405,6 +2406,7 @@ static zend_object *pdo_row_new(zend_class_entry *ce) { pdo_row_t *row = zend_object_alloc(sizeof(pdo_row_t), ce); zend_object_std_init(&row->std, ce); + object_properties_init(&row->std, ce); return &row->std; } diff --git a/ext/pdo_sqlite/tests/gh18114.phpt b/ext/pdo_sqlite/tests/gh18114.phpt new file mode 100644 index 0000000000000..6155bceeae9ba --- /dev/null +++ b/ext/pdo_sqlite/tests/gh18114.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-18114 (pdo lazy object crash) +--EXTENSIONS-- +pdo_sqlite +--XLEAK-- +See https://github.com/php/php-src/issues/18114#issuecomment-2738069692, will be fixed in a later PR on lower branches +--FILE-- +query('select 1 as queryString'); +foreach ($x->fetch(PDO::FETCH_LAZY) as $entry) { + var_dump($entry); +} +echo "Done\n"; +?> +--EXPECT-- +Done From 948868470324c0cf8f920ed1132719c55e496d2b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:48:58 +0100 Subject: [PATCH 136/503] Add test for GH-18113 Fixed in https://github.com/dstogov/ir/pull/110 and merged via b932c267. Closes GH-18113. --- NEWS | 2 ++ ext/opcache/tests/jit/gh18113.phpt | 47 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 ext/opcache/tests/jit/gh18113.phpt diff --git a/NEWS b/NEWS index 91331aadba925..28706b7d67970 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,8 @@ PHP NEWS . Fixed bug GH-17966 (Symfony JIT 1205 assertion failure). (nielsdos) . Fixed bug GH-18037 (SEGV Zend/zend_execute.c). (nielsdos) . Fixed bug GH-18050 (IN_ARRAY optimization in DFA pass is broken). (ilutov) + . Fixed bug GH-18113 (stack-buffer-overflow ext/opcache/jit/ir/ir_sccp.c). + (nielsdos) - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/ext/opcache/tests/jit/gh18113.phpt b/ext/opcache/tests/jit/gh18113.phpt new file mode 100644 index 0000000000000..194bb403032b9 --- /dev/null +++ b/ext/opcache/tests/jit/gh18113.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-18113 (stack-buffer-overflow ext/opcache/jit/ir/ir_sccp.c) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1205 +--FILE-- + +--EXPECT-- +Done From e9c029624031a4ce53e75f5a05997c7b95decad4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:33:40 +0100 Subject: [PATCH 137/503] Fix GH-18112: NULL access with preloading and INI option Preloading shutdown calls request shutdown which will deactivate the virtual cwd state. However, further startup code still assumes the state that was set by virtual_cwd_startup(). So we need to reactivate it manually. Creating a test was a bit difficult because the INI setting I wanted to test this with is overridden by the test runner apparently. To reproduce the issue, create an empty file test.php and execute this in a ZTS build: `php -d opcache.preload=./ext/opcache/tests/preload_class_alias_2.inc -d "error_log=" -d "allow_url_include=1" test.php` Closes GH-18117. --- NEWS | 3 +++ ext/opcache/ZendAccelerator.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/NEWS b/NEWS index 46510db971ea7..d639cd27f0cf6 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,9 @@ PHP NEWS . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) +- Opcache: + . Fixed bug GH-18112 (NULL access with preloading and INI option). (nielsdos) + - SPL: . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index eac5cbbc41f7d..e3f7ca18151e5 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4662,6 +4662,11 @@ static zend_result accel_finish_startup_preload(bool in_child) EG(class_table) = NULL; EG(function_table) = NULL; PG(report_memleaks) = orig_report_memleaks; +#ifdef ZTS + /* Reset the virtual CWD state back to the original state created by virtual_cwd_startup(). + * This is necessary because the normal startup code assumes the CWD state is active. */ + virtual_cwd_activate(); +#endif } else { zend_shared_alloc_unlock(); ret = FAILURE; From 6af240d8dad7375611fb823cdc93201f240e7e4e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 20 Mar 2025 19:14:09 +0100 Subject: [PATCH 138/503] [ci skip] Fix NEWS order --- NEWS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index d639cd27f0cf6..49b80ebb7aee0 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,13 @@ PHP NEWS . Fix weird unpack behaviour in DOM. (nielsdos) . Fix xinclude destruction of live attributes. (nielsdos) +- Embed: + . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) + +- Fuzzer: + . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI). + (Lung-Alexandra) + - GD: . Fixed bug GH-17984 (calls with arguments as array with references). (David Carlier) @@ -23,13 +30,6 @@ PHP NEWS (David Carlier) . Fix UConverter::transcode with substitutes as references. (David Carlier) -- Embed: - . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) - -- Fuzzer: - . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI). - (Lung-Alexandra) - - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) From 2dde07af55bb36d050f08dde4a7dba4f3cc1f181 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 20 Mar 2025 19:21:27 +0100 Subject: [PATCH 139/503] Fix memory leak when destroying PDORow This should call zend_object_std_dtor() to clean the property table etc. This also has a semantic influence because previously weak refs were not notified for example. This fixes the final issue in GH-18114 (the crash was master-only and fixed already). Closes GH-18114. Closes GH-18123. --- NEWS | 3 +++ ext/pdo/pdo_stmt.c | 1 + ext/pdo_sqlite/tests/gh18114.phpt | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 ext/pdo_sqlite/tests/gh18114.phpt diff --git a/NEWS b/NEWS index 49b80ebb7aee0..24db3cc4fbe76 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,9 @@ PHP NEWS - Opcache: . Fixed bug GH-18112 (NULL access with preloading and INI option). (nielsdos) +- PDO: + . Fix memory leak when destroying PDORow. (nielsdos) + - SPL: . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 6aec99026232b..efbf519e5411e 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2506,6 +2506,7 @@ void pdo_row_free_storage(zend_object *std) ZVAL_UNDEF(&row->stmt->lazy_object_ref); OBJ_RELEASE(&row->stmt->std); } + zend_object_std_dtor(std); } zend_object *pdo_row_new(zend_class_entry *ce) diff --git a/ext/pdo_sqlite/tests/gh18114.phpt b/ext/pdo_sqlite/tests/gh18114.phpt new file mode 100644 index 0000000000000..850558845485a --- /dev/null +++ b/ext/pdo_sqlite/tests/gh18114.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-18114 (pdo lazy object crash) +--EXTENSIONS-- +pdo_sqlite +--FILE-- +query('select 1 as queryString'); +$data = $x->fetch(PDO::FETCH_LAZY); +foreach ($data as $entry) { + var_dump($entry); +} +var_dump((array) $data); +echo "Done\n"; +?> +--EXPECT-- +array(0) { +} +Done From 209f4c296ec6a08c721afdf17d787db4b5fd37d0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 20 Mar 2025 09:26:26 +0100 Subject: [PATCH 140/503] Fix #66049 Typemap can break parsing in parse_packet_soap leading to a segfault --- ext/soap/php_packet_soap.c | 3 ++ ext/soap/tests/bugs/bug66049.phpt | 48 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 ext/soap/tests/bugs/bug66049.phpt diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c index c93451506ee3b..325821cd1fd7d 100644 --- a/ext/soap/php_packet_soap.c +++ b/ext/soap/php_packet_soap.c @@ -192,6 +192,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction if (tmp != NULL && tmp->children != NULL) { zval zv; master_to_zval(&zv, get_conversion(IS_STRING), tmp); + convert_to_string(&zv) faultstring = Z_STR(zv); } @@ -199,6 +200,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction if (tmp != NULL && tmp->children != NULL) { zval zv; master_to_zval(&zv, get_conversion(IS_STRING), tmp); + convert_to_string(&zv) faultactor = Z_STR(zv); } @@ -222,6 +224,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction if (tmp != NULL && tmp->children != NULL) { zval zv; master_to_zval(&zv, get_conversion(IS_STRING), tmp); + convert_to_string(&zv) faultstring = Z_STR(zv); } } diff --git a/ext/soap/tests/bugs/bug66049.phpt b/ext/soap/tests/bugs/bug66049.phpt new file mode 100644 index 0000000000000..e48845a8a142b --- /dev/null +++ b/ext/soap/tests/bugs/bug66049.phpt @@ -0,0 +1,48 @@ +--TEST-- +Fix #66049 Typemap can break parsing in parse_packet_soap leading to a segfault +--EXTENSIONS-- +soap +--INI-- +soap.wsdl_cache_enabled=0 +--FILE-- + + + + SOAP-ENV:Servernot present + '; + return $res; + } +} + +try { + $client=new TestSoapClient(null, [ + 'uri' => 'test://', + 'location' => 'test://', + 'typemap' => [[ + "type_ns" => "http://www.w3.org/2001/XMLSchema", + "type_name" => "string", + "from_xml" => "soap_string_from_xml" + ]]]); + $client->Mist(""); +} catch (SoapFault $e) { + var_dump($e->faultstring); + var_dump($e->faultcode); +} +?> +Done +--EXPECT-- +soap_string_from_xml +string(3) "2.3" +string(15) "SOAP-ENV:Server" +Done From 7e6a36889c2064029e948ce934203b17adc39319 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 21 Mar 2025 08:25:05 +0100 Subject: [PATCH 141/503] NEWS for #66049 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 24db3cc4fbe76..0dce55195c180 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,10 @@ PHP NEWS - PDO: . Fix memory leak when destroying PDORow. (nielsdos) +- SOAP: + . Fixed bug #66049 (Typemap can break parsing in parse_packet_soap leading to + a segfault) . (Remi) + - SPL: . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) From 58e4adcd63d0af788f8e06fe9bd79a5fa9df5f1b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 21 Mar 2025 08:25:49 +0100 Subject: [PATCH 142/503] NEWS for #66049 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 64c4ee19eff48..2d92594daf34b 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,10 @@ PHP NEWS - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) +- SOAP: + . Fixed bug #66049 (Typemap can break parsing in parse_packet_soap leading to + a segfault) . (Remi) + - SPL: . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) From 447d143b9d525d0cd4a7759af2357c7aec76a8d9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 21 Mar 2025 11:47:47 +0100 Subject: [PATCH 143/503] Fixed bug GH-13193 again Closes GH-13193. --- NEWS | 2 ++ Zend/zend_gc.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0dce55195c180..02365adeb6463 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS (Arnaud) . Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown). (Arnaud) + . Fixed bug GH-13193 again (Significant performance degradation in 'foreach'). + (nielsdos) - DOM: . Fix weird unpack behaviour in DOM. (nielsdos) diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 3016ff8a1af04..20a764f9a3a24 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -1783,7 +1783,7 @@ ZEND_API int zend_gc_collect_cycles(void) bool did_rerun_gc = 0; zend_hrtime_t start_time = zend_hrtime(); - if (GC_G(num_roots) && GC_G(gc_active)) { + if (GC_G(num_roots) && !GC_G(gc_active)) { zend_gc_remove_root_tmpvars(); } From fa3c1c81d548953853f4cc06f96615b0ec9007e1 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Thu, 20 Mar 2025 10:27:12 -0700 Subject: [PATCH 144/503] Fix GH-17836: zend_vm_gen.php shouldn't break on Windows line endings Closes GH-18121. --- NEWS | 4 ++++ Zend/zend_vm_gen.php | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/NEWS b/NEWS index 02365adeb6463..1e426e1f4c989 100644 --- a/NEWS +++ b/NEWS @@ -53,6 +53,10 @@ PHP NEWS - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) +- Windows: + . Fixed bug GH-17836 (zend_vm_gen.php shouldn't break on Windows line + endings). (DanielEScherzer) + 13 Mar 2025, PHP 8.3.19 - BCMath: diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 79b7653871272..64105f5659f17 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2401,6 +2401,12 @@ function gen_vm($def, $skel) { $max_opcode = 0; $extra_num = 256; foreach ($in as $line) { + // Handle Windows line endings, GH-17836; since a bunch of regular + // expressions below test for a newline at the end, just update the + // ending + if (substr($line, -2) === "\r\n") { + $line = substr_replace($line, "\n", -2); + } ++$lineno; if (strpos($line,"ZEND_VM_HANDLER(") === 0 || strpos($line,"ZEND_VM_INLINE_HANDLER(") === 0 || From 2ec8d37eb47681b547437cad77fd31b5ca9b3f3d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 18 Mar 2025 23:23:36 +0100 Subject: [PATCH 145/503] Fix GH-18107: Opcache CFG jmp optimization with try-finally breaks the exception table If there's a try-finally where the try_op starts on a basic block with a single JMP, and the JMP optimization causes that basic block to become unreachable, then we update try_op. In this case, there is no catch_op, so try_op is erroneously set to 0, we should instead set it to `b->start`. Closes GH-18110. --- NEWS | 2 ++ Zend/Optimizer/zend_cfg.c | 6 +++- ext/opcache/tests/opt/gh18107_1.phpt | 45 ++++++++++++++++++++++++ ext/opcache/tests/opt/gh18107_2.phpt | 52 ++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/gh18107_1.phpt create mode 100644 ext/opcache/tests/opt/gh18107_2.phpt diff --git a/NEWS b/NEWS index 1e426e1f4c989..caad04f9d0895 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ PHP NEWS - Opcache: . Fixed bug GH-18112 (NULL access with preloading and INI option). (nielsdos) + . Fixed bug GH-18107 (Opcache CFG jmp optimization with try-finally breaks + the exception table). (nielsdos) - PDO: . Fix memory leak when destroying PDORow. (nielsdos) diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index ce7d078bb957e..05cb36dd34428 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -144,7 +144,11 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * end = blocks + block_map[op_array->try_catch_array[j].finally_op]; while (b != end) { if (b->flags & ZEND_BB_REACHABLE) { - op_array->try_catch_array[j].try_op = op_array->try_catch_array[j].catch_op; + /* In case we get here, there is no live try block but there is a live finally block. + * If we do have catch_op set, we need to set it to the first catch block to satisfy + * the constraint try_op <= catch_op <= finally_op */ + op_array->try_catch_array[j].try_op = + op_array->try_catch_array[j].catch_op ? op_array->try_catch_array[j].catch_op : b->start; changed = 1; zend_mark_reachable(op_array->opcodes, cfg, blocks + block_map[op_array->try_catch_array[j].try_op]); break; diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt new file mode 100644 index 0000000000000..0bb5b3201f203 --- /dev/null +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -0,0 +1,45 @@ +--TEST-- +GH-18107 (Opcache CFG jmp optimization with try-finally breaks the exception table) +--CREDITS-- +SpencerMalone +--EXTENSIONS-- +opcache +--INI-- +opcache.optimization_level=0x10 +opcache.opt_debug_level=0x20000 +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T1 = ISSET_ISEMPTY_CV (isset) CV0($badvar) +0001 JMPNZ T1 0006 +0002 V3 = NEW 1 string("Exception") +0003 SEND_VAL_EX string("Should happen") 1 +0004 DO_FCALL +0005 THROW V3 +0006 JMP 0006 +0007 V6 = NEW 1 string("Exception") +0008 SEND_VAL_EX string("Should not happen") 1 +0009 DO_FCALL +0010 THROW V6 +0011 FAST_RET T5 +EXCEPTION TABLE: + 0006, -, 0007, 0011 +Fatal error: Uncaught Exception: Should happen in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt new file mode 100644 index 0000000000000..0f4f66a4591bc --- /dev/null +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -0,0 +1,52 @@ +--TEST-- +GH-18107 (Opcache CFG jmp optimization with try-finally breaks the exception table) +--CREDITS-- +SpencerMalone +--EXTENSIONS-- +opcache +--INI-- +opcache.optimization_level=0x10 +opcache.opt_debug_level=0x20000 +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T2 = ISSET_ISEMPTY_CV (isset) CV0($badvar) +0001 JMPNZ T2 0008 +0002 V4 = NEW 1 string("Exception") +0003 SEND_VAL_EX string("Should happen") 1 +0004 DO_FCALL +0005 THROW V4 +0006 CV1($e) = CATCH string("Throwable") +0007 ECHO string("foo") +0008 T6 = FAST_CALL 0010 +0009 JMP 0015 +0010 V7 = NEW 1 string("Exception") +0011 SEND_VAL_EX string("Should not happen") 1 +0012 DO_FCALL +0013 THROW V7 +0014 FAST_RET T6 +0015 RETURN int(1) +EXCEPTION TABLE: + 0006, 0006, 0010, 0014 +Fatal error: Uncaught Exception: Should happen in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d From 484d528b40645f823047b53bcb5ba4228fb612c0 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 21 Mar 2025 13:13:25 +0000 Subject: [PATCH 146/503] ext/standard: Use usual not empty error for proc_open() (#18083) --- ext/standard/proc_open.c | 4 ++-- ext/standard/tests/general_functions/proc_open_array.phpt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 84984188f2710..06a3f916a849c 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -1247,8 +1247,8 @@ PHP_FUNCTION(proc_open) if (command_ht) { uint32_t num_elems = zend_hash_num_elements(command_ht); - if (num_elems == 0) { - zend_argument_value_error(1, "must have at least one element"); + if (UNEXPECTED(num_elems == 0)) { + zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } diff --git a/ext/standard/tests/general_functions/proc_open_array.phpt b/ext/standard/tests/general_functions/proc_open_array.phpt index 964b8391cb615..a76f1111ef268 100644 --- a/ext/standard/tests/general_functions/proc_open_array.phpt +++ b/ext/standard/tests/general_functions/proc_open_array.phpt @@ -76,7 +76,7 @@ proc_close($proc); ?> --EXPECT-- Empty command array: -proc_open(): Argument #1 ($command) must have at least one element +proc_open(): Argument #1 ($command) must not be empty Nul byte in program name: Command array element 1 contains a null byte From 8823f89a3282f1a77c2416779f9b0136c213e9fb Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 21 Mar 2025 06:23:03 -0700 Subject: [PATCH 147/503] Fix intl tests for icu 77 (#18125) --- ext/intl/tests/locale_get_display_name8.phpt | 12 ++++++------ ext/intl/tests/locale_get_display_variant2.phpt | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/intl/tests/locale_get_display_name8.phpt b/ext/intl/tests/locale_get_display_name8.phpt index e8c1ed958ac1c..aa91ee4c3b8ca 100644 --- a/ext/intl/tests/locale_get_display_name8.phpt +++ b/ext/intl/tests/locale_get_display_name8.phpt @@ -112,9 +112,9 @@ disp_locale=fr : display_name=slovène #Italie, NEDIS_KIRTI# disp_locale=de : display_name=Slowenisch #Italien, NEDIS_KIRTI# ----------------- locale='sl_IT_nedis-a-kirti-x-xyz' -disp_locale=en : display_name=Slovenian #Italy, NEDIS_A_KIRTI_X_XYZ# -disp_locale=fr : display_name=slovène #Italie, NEDIS_A_KIRTI_X_XYZ# -disp_locale=de : display_name=Slowenisch #Italien, NEDIS_A_KIRTI_X_XYZ# +disp_locale=en : display_name=Slovenian #Italy, NEDIS_A_KIRTI(_X_XYZ)?# +disp_locale=fr : display_name=slovène #Italie, NEDIS_A_KIRTI(_X_XYZ)?# +disp_locale=de : display_name=Slowenisch #Italien, NEDIS_A_KIRTI(_X_XYZ)?# ----------------- locale='sl_IT_rozaj' disp_locale=en : display_name=Slovenian #Italy, Resian# @@ -317,9 +317,9 @@ disp_locale=fr : display_name=anglais #États-Unis, attribute=islamcal# disp_locale=de : display_name=Englisch #Vereinigte Staaten, attribute=islamcal# ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_name=Chinese #China(, A_MYEXT_X_PRIVATE)?, a=myext, Private-Use=private# -disp_locale=fr : display_name=chinois #Chine(, A_MYEXT_X_PRIVATE)?, a=myext, usage privé=private# -disp_locale=de : display_name=Chinesisch #China(, A_MYEXT_X_PRIVATE)?, a=myext, Privatnutzung=private# +disp_locale=en : display_name=Chinese #China(, A_MYEXT(_X_PRIVATE)?)?, a=myext, Private-Use=private# +disp_locale=fr : display_name=chinois #Chine(, A_MYEXT(_X_PRIVATE)?)?, a=myext, usage privé=private# +disp_locale=de : display_name=Chinesisch #China(, A_MYEXT(_X_PRIVATE)?)?, a=myext, Privatnutzung=private# ----------------- locale='en-a-myExt-b-another' disp_locale=en : display_name=English #(A_MYEXT_B_ANOTHER, )?a=myext, b=another# diff --git a/ext/intl/tests/locale_get_display_variant2.phpt b/ext/intl/tests/locale_get_display_variant2.phpt index e56154902dde9..8e815e8c4e52a 100644 --- a/ext/intl/tests/locale_get_display_variant2.phpt +++ b/ext/intl/tests/locale_get_display_variant2.phpt @@ -248,9 +248,9 @@ disp_locale=fr : display_variant= disp_locale=de : display_variant= ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_variant=(A_MYEXT_X_PRIVATE)? -disp_locale=fr : display_variant=(A_MYEXT_X_PRIVATE)? -disp_locale=de : display_variant=(A_MYEXT_X_PRIVATE)? +disp_locale=en : display_variant=(A_MYEXT(_X_PRIVATE)?)? +disp_locale=fr : display_variant=(A_MYEXT(_X_PRIVATE)?)? +disp_locale=de : display_variant=(A_MYEXT(_X_PRIVATE)?)? ----------------- locale='en-a-myExt-b-another' disp_locale=en : display_variant=((A_)?MYEXT_B_ANOTHER)? From 071f707a6d883d46a3c6d932ec4045345d690e25 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:35:26 +0100 Subject: [PATCH 148/503] [ci skip] Make sure opcache can output in these tests --- ext/opcache/tests/opt/gh18107_1.phpt | 2 ++ ext/opcache/tests/opt/gh18107_2.phpt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt index 0bb5b3201f203..c99fa7efa40d3 100644 --- a/ext/opcache/tests/opt/gh18107_1.phpt +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -5,6 +5,8 @@ SpencerMalone --EXTENSIONS-- opcache --INI-- +opcache.enable=1 +opcache.enable_cli=1 opcache.optimization_level=0x10 opcache.opt_debug_level=0x20000 --FILE-- diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt index 0f4f66a4591bc..573bcd5ae4a6f 100644 --- a/ext/opcache/tests/opt/gh18107_2.phpt +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -5,6 +5,8 @@ SpencerMalone --EXTENSIONS-- opcache --INI-- +opcache.enable=1 +opcache.enable_cli=1 opcache.optimization_level=0x10 opcache.opt_debug_level=0x20000 --FILE-- From 862236239430f6c99c391260dc6f3e7080d22c81 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Fri, 21 Mar 2025 18:30:22 +0100 Subject: [PATCH 149/503] Remove unused strcasecmp definition (#17050) The strcasecmp usage was removed via dc5f3b95627526d2e5729ae779e7bc82ee5fa3f3. --- ext/mbstring/libmbfl/mbfl/mbfl_encoding.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c index 6e44f68b85790..63ca5bc6a2e75 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c +++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c @@ -31,7 +31,7 @@ #include "libmbfl/config.h" #ifdef HAVE_STRINGS_H - /* For strcasecmp */ + /* For strncasecmp */ #include #endif @@ -54,13 +54,6 @@ #include "filters/mbfilter_htmlent.h" #include "filters/mbfilter_singlebyte.h" -#ifndef HAVE_STRCASECMP -#ifdef HAVE_STRICMP -#define strcasecmp stricmp -#endif -#endif - - static const mbfl_encoding *mbfl_encoding_ptr_list[] = { &mbfl_encoding_base64, &mbfl_encoding_uuencode, From a28fb52719020ed737a869b5355892318cc13d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 22 Mar 2025 16:34:26 +0100 Subject: [PATCH 150/503] zend_vm_def: Use `FREE_OP1()` in ZEND_FREE handler (#18131) This is for consistency with other opcode handlers. It does not have an effect on the generated VM. --- Zend/zend_vm_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 467b5c6193310..8770cab3826d8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3207,7 +3207,7 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY) USE_OPLINE SAVE_OPLINE(); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } From 7d4ed8af0371c0bfae949431354b06119bb4e7fb Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 17 Mar 2025 23:01:22 +0100 Subject: [PATCH 151/503] Fix "expecting token" error for ampersand Currently, this is only handled for the "unexpected token" part of the message, but not the "expected" part. Fixes GH-18026 Closes GH-18101 --- NEWS | 1 + Zend/tests/gh18026.phpt | 12 ++++++++++++ Zend/zend_language_parser.y | 8 ++++++++ 3 files changed, 21 insertions(+) create mode 100644 Zend/tests/gh18026.phpt diff --git a/NEWS b/NEWS index e2c67a4a24d12..fcb849ef98a58 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,7 @@ PHP NEWS (ilutov) . Fixed bug GH-18033 (NULL-ptr dereference when using register_tick_function in destructor). (nielsdos) + . Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/Zend/tests/gh18026.phpt b/Zend/tests/gh18026.phpt new file mode 100644 index 0000000000000..0e33e349b12fe --- /dev/null +++ b/Zend/tests/gh18026.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-18026: Confusing "amp" reference in parser error +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected token ")", expecting token "&" in %s on line %d diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index c671b3a295e5c..1f117d142c158 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -1819,6 +1819,14 @@ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) return sizeof("\"\\\"")-1; } + /* We used "amp" as a dummy label to avoid a duplicate token literal warning. */ + if (strcmp(toktype, "\"amp\"") == 0) { + if (yyres) { + yystpcpy(yyres, "token \"&\""); + } + return sizeof("token \"&\"")-1; + } + /* Strip off the outer quote marks */ if (toktype_len >= 2 && *toktype == '"') { toktype++; From d5bdf8f5086dabb60a65d0219a3dc9797caf8b81 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 17 Mar 2025 16:25:42 +0100 Subject: [PATCH 152/503] Fix segfault when evaluating const expr default value of child prop with added hooks Introduced by GH-17870. Not adding a NEWS entry since this is fixed in the same version. Fixes oss-fuzz #403816122 Closes GH-18098 --- Zend/tests/oss-fuzz-403816122.phpt | 22 ++++++++++++++ Zend/zend_API.c | 6 +++- Zend/zend_lazy_objects.c | 46 +++++++++++++++++++----------- ext/opcache/ZendAccelerator.c | 8 ++++-- 4 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 Zend/tests/oss-fuzz-403816122.phpt diff --git a/Zend/tests/oss-fuzz-403816122.phpt b/Zend/tests/oss-fuzz-403816122.phpt new file mode 100644 index 0000000000000..b9d9400609fc6 --- /dev/null +++ b/Zend/tests/oss-fuzz-403816122.phpt @@ -0,0 +1,22 @@ +--TEST-- +OSS-Fuzz #403816122: Segfault when initializing default properties of child prop with added hooks +--FILE-- + 'y'; + } +} + +var_dump((new C)->prop); + +?> +--EXPECT-- +string(1) "y" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 1021a6f7bd508..5aac3c1f7d77c 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1613,8 +1613,12 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) / /* Use the default properties table to also update initializers of private properties * that have been shadowed in a child class. */ for (uint32_t i = 0; i < class_type->default_properties_count; i++) { - val = &default_properties_table[i]; prop_info = class_type->properties_info_table[i]; + if (!prop_info) { + continue; + } + + val = &default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; if (Z_TYPE_P(val) == IS_CONSTANT_AST && UNEXPECTED(update_property(val, prop_info) != SUCCESS)) { return FAILURE; diff --git a/Zend/zend_lazy_objects.c b/Zend/zend_lazy_objects.c index 41ba3e1cd288d..d1b950160e1cc 100644 --- a/Zend/zend_lazy_objects.c +++ b/Zend/zend_lazy_objects.c @@ -268,14 +268,17 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj, obj = zend_objects_new(reflection_ce); - for (int i = 0; i < obj->ce->default_properties_count; i++) { + /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */ + for (int i = obj->ce->default_properties_count - 1; i >= 0; i--) { zval *p = &obj->properties_table[i]; ZVAL_UNDEF(p); - if (EXPECTED(obj->ce->properties_info_table[i])) { + Z_PROP_FLAG_P(p) = 0; + + zend_property_info *prop_info = obj->ce->properties_info_table[i]; + if (prop_info) { + zval *p = &obj->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; Z_PROP_FLAG_P(p) = IS_PROP_UNINIT | IS_PROP_LAZY; lazy_properties_count++; - } else { - Z_PROP_FLAG_P(p) = 0; } } } else { @@ -326,7 +329,7 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj, for (int i = 0; i < reflection_ce->default_properties_count; i++) { zend_property_info *prop_info = obj->ce->properties_info_table[i]; if (EXPECTED(prop_info)) { - zval *p = &obj->properties_table[i]; + zval *p = &obj->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; if (Z_TYPE_P(p) != IS_UNDEF) { if ((prop_info->flags & ZEND_ACC_READONLY) && !(Z_PROP_FLAG_P(p) & IS_PROP_REINITABLE) /* TODO: test final property */ @@ -408,12 +411,16 @@ static void zend_lazy_object_revert_init(zend_object *obj, zval *properties_tabl zval *properties_table = obj->properties_table; for (int i = 0; i < ce->default_properties_count; i++) { - zval *p = &properties_table[i]; + zend_property_info *prop_info = ce->properties_info_table[i]; + if (!prop_info) { + continue; + } + + zval *p = &properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; zend_object_dtor_property(obj, p); - ZVAL_COPY_VALUE_PROP(p, &properties_table_snapshot[i]); + ZVAL_COPY_VALUE_PROP(p, &properties_table_snapshot[OBJ_PROP_TO_NUM(prop_info->offset)]); - zend_property_info *prop_info = ce->properties_info_table[i]; - if (Z_ISREF_P(p) && prop_info && ZEND_TYPE_IS_SET(prop_info->type)) { + if (Z_ISREF_P(p) && ZEND_TYPE_IS_SET(prop_info->type)) { ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(p), prop_info); } } @@ -526,10 +533,12 @@ static zend_object *zend_lazy_object_init_proxy(zend_object *obj) obj->properties = NULL; for (int i = 0; i < Z_OBJ(retval)->ce->default_properties_count; i++) { - if (EXPECTED(Z_OBJ(retval)->ce->properties_info_table[i])) { - zend_object_dtor_property(obj, &obj->properties_table[i]); - ZVAL_UNDEF(&obj->properties_table[i]); - Z_PROP_FLAG_P(&obj->properties_table[i]) = IS_PROP_UNINIT | IS_PROP_LAZY; + zend_property_info *prop_info = Z_OBJ(retval)->ce->properties_info_table[i]; + if (EXPECTED(prop_info)) { + zval *prop = &obj->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; + zend_object_dtor_property(obj, prop); + ZVAL_UNDEF(prop); + Z_PROP_FLAG_P(prop) = IS_PROP_UNINIT | IS_PROP_LAZY; } } @@ -722,13 +731,16 @@ zend_object *zend_lazy_object_clone(zend_object *old_obj) zend_class_entry *ce = old_obj->ce; zend_object *new_proxy = zend_objects_new(ce); - for (int i = 0; i < ce->default_properties_count; i++) { + /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */ + for (int i = ce->default_properties_count - 1; i >= 0; i--) { zval *p = &new_proxy->properties_table[i]; ZVAL_UNDEF(p); - if (EXPECTED(ce->properties_info_table[i])) { + Z_PROP_FLAG_P(p) = 0; + + zend_property_info *prop_info = ce->properties_info_table[i]; + if (prop_info) { + zval *p = &new_proxy->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]; Z_PROP_FLAG_P(p) = IS_PROP_UNINIT | IS_PROP_LAZY; - } else { - Z_PROP_FLAG_P(p) = 0; } } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index fbfd3cfa73bca..459449d85f23c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3815,9 +3815,13 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) bool resolved = true; for (i = 0; i < ce->default_properties_count; i++) { - val = &ce->default_properties_table[i]; + zend_property_info *prop = ce->properties_info_table[i]; + if (!prop) { + continue; + } + + val = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop->offset)]; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - zend_property_info *prop = ce->properties_info_table[i]; if (UNEXPECTED(zval_update_constant_ex(val, prop->ce) != SUCCESS)) { resolved = ok = false; } From 345d229385381c62a0378d9b8390f4c610425337 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 23 Mar 2025 20:39:34 +0000 Subject: [PATCH 153/503] ext/dba: Reduce scope of dba_handler variables --- ext/dba/dba.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 7fdc1cf6e1eff..38040f209d98e 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -435,10 +435,9 @@ PHP_MSHUTDOWN_FUNCTION(dba) /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(dba) { - const dba_handler *hptr; smart_str handlers = {0}; - for(hptr = handler; hptr->name; hptr++) { + for (const dba_handler *hptr = handler; hptr->name; hptr++) { smart_str_appends(&handlers, hptr->name); smart_str_appendc(&handlers, ' '); } @@ -1252,7 +1251,6 @@ PHP_FUNCTION(dba_sync) /* {{{ List configured database handlers */ PHP_FUNCTION(dba_handlers) { - const dba_handler *hptr; bool full_info = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &full_info) == FAILURE) { @@ -1261,7 +1259,7 @@ PHP_FUNCTION(dba_handlers) array_init(return_value); - for(hptr = handler; hptr->name; hptr++) { + for (const dba_handler *hptr = handler; hptr->name; hptr++) { if (full_info) { // TODO: avoid reallocation ??? char *str = hptr->info(hptr, NULL); From 0c8a7a77a85b282da1e346b8a841d1c369d1911c Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 24 Mar 2025 10:06:32 +0000 Subject: [PATCH 154/503] Updated to version 2025.2 (2025b) --- ext/date/lib/timezonedb.h | 2251 ++++++++++++++++++++----------------- 1 file changed, 1239 insertions(+), 1012 deletions(-) diff --git a/ext/date/lib/timezonedb.h b/ext/date/lib/timezonedb.h index 3c75462009afb..a4cbb618799c8 100644 --- a/ext/date/lib/timezonedb.h +++ b/ext/date/lib/timezonedb.h @@ -4,7 +4,7 @@ #endif #ifdef TIMELIB_SUPPORT_SLIM_FILE -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x00008E }, { (char*) "Africa/Addis_Ababa" , 0x000356 }, @@ -104,508 +104,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x00ADD3 }, { (char*) "America/Cordoba" , 0x00AE74 }, { (char*) "America/Costa_Rica" , 0x00B144 }, - { (char*) "America/Creston" , 0x00B238 }, - { (char*) "America/Cuiaba" , 0x00B2F4 }, - { (char*) "America/Curacao" , 0x00B6B1 }, - { (char*) "America/Danmarkshavn" , 0x00B754 }, - { (char*) "America/Dawson" , 0x00B939 }, - { (char*) "America/Dawson_Creek" , 0x00BD5C }, - { (char*) "America/Denver" , 0x00C033 }, - { (char*) "America/Detroit" , 0x00C466 }, - { (char*) "America/Dominica" , 0x00C80E }, - { (char*) "America/Edmonton" , 0x00C89C }, - { (char*) "America/Eirunepe" , 0x00CC94 }, - { (char*) "America/El_Salvador" , 0x00CE63 }, - { (char*) "America/Ensenada" , 0x00CF1F }, - { (char*) "America/Fort_Nelson" , 0x00D362 }, - { (char*) "America/Fort_Wayne" , 0x00D92A }, - { (char*) "America/Fortaleza" , 0x00DB49 }, - { (char*) "America/Glace_Bay" , 0x00DD5F }, - { (char*) "America/Godthab" , 0x00E0F6 }, - { (char*) "America/Goose_Bay" , 0x00E4C7 }, - { (char*) "America/Grand_Turk" , 0x00EB1F }, - { (char*) "America/Grenada" , 0x00EE80 }, - { (char*) "America/Guadeloupe" , 0x00EF0E }, - { (char*) "America/Guatemala" , 0x00EF9C }, - { (char*) "America/Guayaquil" , 0x00F07C }, - { (char*) "America/Guyana" , 0x00F14D }, - { (char*) "America/Halifax" , 0x00F20E }, - { (char*) "America/Havana" , 0x00F8C0 }, - { (char*) "America/Hermosillo" , 0x00FD29 }, - { (char*) "America/Indiana/Indianapolis" , 0x00FE3D }, - { (char*) "America/Indiana/Knox" , 0x010075 }, - { (char*) "America/Indiana/Marengo" , 0x01048E }, - { (char*) "America/Indiana/Petersburg" , 0x0106E8 }, - { (char*) "America/Indiana/Tell_City" , 0x0109B2 }, - { (char*) "America/Indiana/Vevay" , 0x010BDC }, - { (char*) "America/Indiana/Vincennes" , 0x010D73 }, - { (char*) "America/Indiana/Winamac" , 0x010FC9 }, - { (char*) "America/Indianapolis" , 0x011246 }, - { (char*) "America/Inuvik" , 0x011465 }, - { (char*) "America/Iqaluit" , 0x0117B6 }, - { (char*) "America/Jamaica" , 0x011B32 }, - { (char*) "America/Jujuy" , 0x011C91 }, - { (char*) "America/Juneau" , 0x011F4F }, - { (char*) "America/Kentucky/Louisville" , 0x012335 }, - { (char*) "America/Kentucky/Monticello" , 0x012839 }, - { (char*) "America/Knox_IN" , 0x012C25 }, - { (char*) "America/Kralendijk" , 0x013029 }, - { (char*) "America/La_Paz" , 0x0130E6 }, - { (char*) "America/Lima" , 0x01319C }, - { (char*) "America/Los_Angeles" , 0x0132C3 }, - { (char*) "America/Louisville" , 0x0137E4 }, - { (char*) "America/Lower_Princes" , 0x013CCA }, - { (char*) "America/Maceio" , 0x013D87 }, - { (char*) "America/Managua" , 0x013F99 }, - { (char*) "America/Manaus" , 0x0140CC }, - { (char*) "America/Marigot" , 0x014283 }, - { (char*) "America/Martinique" , 0x014340 }, - { (char*) "America/Matamoros" , 0x0143FE }, - { (char*) "America/Mazatlan" , 0x0145EB }, - { (char*) "America/Mendoza" , 0x0148DB }, - { (char*) "America/Menominee" , 0x014BAB }, - { (char*) "America/Merida" , 0x014F6B }, - { (char*) "America/Metlakatla" , 0x015216 }, - { (char*) "America/Mexico_City" , 0x015483 }, - { (char*) "America/Miquelon" , 0x0157A2 }, - { (char*) "America/Moncton" , 0x0159D4 }, - { (char*) "America/Monterrey" , 0x015FCD }, - { (char*) "America/Montevideo" , 0x0162D4 }, - { (char*) "America/Montreal" , 0x0166A9 }, - { (char*) "America/Montserrat" , 0x016D6A }, - { (char*) "America/Nassau" , 0x016DF8 }, - { (char*) "America/New_York" , 0x0171F2 }, - { (char*) "America/Nipigon" , 0x0178E2 }, - { (char*) "America/Nome" , 0x017FA3 }, - { (char*) "America/Noronha" , 0x01838B }, - { (char*) "America/North_Dakota/Beulah" , 0x01858B }, - { (char*) "America/North_Dakota/Center" , 0x0189BF }, - { (char*) "America/North_Dakota/New_Salem" , 0x018DBE }, - { (char*) "America/Nuuk" , 0x0191C3 }, - { (char*) "America/Ojinaga" , 0x0195A5 }, - { (char*) "America/Panama" , 0x01989B }, - { (char*) "America/Pangnirtung" , 0x01993C }, - { (char*) "America/Paramaribo" , 0x019C9F }, - { (char*) "America/Phoenix" , 0x019D66 }, - { (char*) "America/Port-au-Prince" , 0x019E7A }, - { (char*) "America/Port_of_Spain" , 0x01A0BB }, - { (char*) "America/Porto_Acre" , 0x01A149 }, - { (char*) "America/Porto_Velho" , 0x01A2F7 }, - { (char*) "America/Puerto_Rico" , 0x01A495 }, - { (char*) "America/Punta_Arenas" , 0x01A552 }, - { (char*) "America/Rainy_River" , 0x01AA34 }, - { (char*) "America/Rankin_Inlet" , 0x01AF4E }, - { (char*) "America/Recife" , 0x01B297 }, - { (char*) "America/Regina" , 0x01B491 }, - { (char*) "America/Resolute" , 0x01B730 }, - { (char*) "America/Rio_Branco" , 0x01BA7A }, - { (char*) "America/Rosario" , 0x01BC2C }, - { (char*) "America/Santa_Isabel" , 0x01BEFC }, - { (char*) "America/Santarem" , 0x01C33F }, - { (char*) "America/Santiago" , 0x01C4EF }, - { (char*) "America/Santo_Domingo" , 0x01CA52 }, - { (char*) "America/Sao_Paulo" , 0x01CB9B }, - { (char*) "America/Scoresbysund" , 0x01CF95 }, - { (char*) "America/Shiprock" , 0x01D396 }, - { (char*) "America/Sitka" , 0x01D7B4 }, - { (char*) "America/St_Barthelemy" , 0x01DB8F }, - { (char*) "America/St_Johns" , 0x01DC4C }, - { (char*) "America/St_Kitts" , 0x01E3C9 }, - { (char*) "America/St_Lucia" , 0x01E457 }, - { (char*) "America/St_Thomas" , 0x01E4F8 }, - { (char*) "America/St_Vincent" , 0x01E586 }, - { (char*) "America/Swift_Current" , 0x01E627 }, - { (char*) "America/Tegucigalpa" , 0x01E7B5 }, - { (char*) "America/Thule" , 0x01E883 }, - { (char*) "America/Thunder_Bay" , 0x01EA64 }, - { (char*) "America/Tijuana" , 0x01F125 }, - { (char*) "America/Toronto" , 0x01F577 }, - { (char*) "America/Tortola" , 0x01FC56 }, - { (char*) "America/Vancouver" , 0x01FCE4 }, - { (char*) "America/Virgin" , 0x02023B }, - { (char*) "America/Whitehorse" , 0x0202F8 }, - { (char*) "America/Winnipeg" , 0x02071B }, - { (char*) "America/Yakutat" , 0x020C52 }, - { (char*) "America/Yellowknife" , 0x021020 }, - { (char*) "Antarctica/Casey" , 0x0213F6 }, - { (char*) "Antarctica/Davis" , 0x021526 }, - { (char*) "Antarctica/DumontDUrville" , 0x0215FC }, - { (char*) "Antarctica/Macquarie" , 0x0216B0 }, - { (char*) "Antarctica/Mawson" , 0x021A9C }, - { (char*) "Antarctica/McMurdo" , 0x021B46 }, - { (char*) "Antarctica/Palmer" , 0x021E78 }, - { (char*) "Antarctica/Rothera" , 0x022201 }, - { (char*) "Antarctica/South_Pole" , 0x022298 }, - { (char*) "Antarctica/Syowa" , 0x0226B7 }, - { (char*) "Antarctica/Troll" , 0x02274D }, - { (char*) "Antarctica/Vostok" , 0x0227FC }, - { (char*) "Arctic/Longyearbyen" , 0x0228B8 }, - { (char*) "Asia/Aden" , 0x022B85 }, - { (char*) "Asia/Almaty" , 0x022C16 }, - { (char*) "Asia/Amman" , 0x022E9E }, - { (char*) "Asia/Anadyr" , 0x02324A }, - { (char*) "Asia/Aqtau" , 0x023550 }, - { (char*) "Asia/Aqtobe" , 0x0237CF }, - { (char*) "Asia/Ashgabat" , 0x023A4F }, - { (char*) "Asia/Ashkhabad" , 0x023BD2 }, - { (char*) "Asia/Atyrau" , 0x023D55 }, - { (char*) "Asia/Baghdad" , 0x023FDE }, - { (char*) "Asia/Bahrain" , 0x024260 }, - { (char*) "Asia/Baku" , 0x024319 }, - { (char*) "Asia/Bangkok" , 0x02460D }, - { (char*) "Asia/Barnaul" , 0x0246B1 }, - { (char*) "Asia/Beirut" , 0x0249BC }, - { (char*) "Asia/Bishkek" , 0x024CA4 }, - { (char*) "Asia/Brunei" , 0x024F1A }, - { (char*) "Asia/Calcutta" , 0x024FC0 }, - { (char*) "Asia/Chita" , 0x0250A8 }, - { (char*) "Asia/Choibalsan" , 0x0253B6 }, - { (char*) "Asia/Chongqing" , 0x025614 }, - { (char*) "Asia/Chungking" , 0x0257A9 }, - { (char*) "Asia/Colombo" , 0x02593E }, - { (char*) "Asia/Dacca" , 0x025A41 }, - { (char*) "Asia/Damascus" , 0x025B34 }, - { (char*) "Asia/Dhaka" , 0x026012 }, - { (char*) "Asia/Dili" , 0x026105 }, - { (char*) "Asia/Dubai" , 0x0261BB }, - { (char*) "Asia/Dushanbe" , 0x02624C }, - { (char*) "Asia/Famagusta" , 0x0263C6 }, - { (char*) "Asia/Gaza" , 0x02678D }, - { (char*) "Asia/Harbin" , 0x027329 }, - { (char*) "Asia/Hebron" , 0x0274BE }, - { (char*) "Asia/Ho_Chi_Minh" , 0x02806B }, - { (char*) "Asia/Hong_Kong" , 0x028163 }, - { (char*) "Asia/Hovd" , 0x028476 }, - { (char*) "Asia/Irkutsk" , 0x0286EA }, - { (char*) "Asia/Istanbul" , 0x028A08 }, - { (char*) "Asia/Jakarta" , 0x028EC4 }, - { (char*) "Asia/Jayapura" , 0x028FD5 }, - { (char*) "Asia/Jerusalem" , 0x0290C2 }, - { (char*) "Asia/Kabul" , 0x029500 }, - { (char*) "Asia/Kamchatka" , 0x0295AB }, - { (char*) "Asia/Karachi" , 0x0298A0 }, - { (char*) "Asia/Kashgar" , 0x0299B6 }, - { (char*) "Asia/Kathmandu" , 0x029A47 }, - { (char*) "Asia/Katmandu" , 0x029AF4 }, - { (char*) "Asia/Khandyga" , 0x029BA1 }, - { (char*) "Asia/Kolkata" , 0x029ED2 }, - { (char*) "Asia/Krasnoyarsk" , 0x029FBA }, - { (char*) "Asia/Kuala_Lumpur" , 0x02A2C4 }, - { (char*) "Asia/Kuching" , 0x02A3E4 }, - { (char*) "Asia/Kuwait" , 0x02A53E }, - { (char*) "Asia/Macao" , 0x02A5CF }, - { (char*) "Asia/Macau" , 0x02A8F2 }, - { (char*) "Asia/Magadan" , 0x02AC15 }, - { (char*) "Asia/Makassar" , 0x02AF20 }, - { (char*) "Asia/Manila" , 0x02B033 }, - { (char*) "Asia/Muscat" , 0x02B151 }, - { (char*) "Asia/Nicosia" , 0x02B1E2 }, - { (char*) "Asia/Novokuznetsk" , 0x02B451 }, - { (char*) "Asia/Novosibirsk" , 0x02B744 }, - { (char*) "Asia/Omsk" , 0x02BA55 }, - { (char*) "Asia/Oral" , 0x02BD53 }, - { (char*) "Asia/Phnom_Penh" , 0x02BFDF }, - { (char*) "Asia/Pontianak" , 0x02C0B3 }, - { (char*) "Asia/Pyongyang" , 0x02C1CC }, - { (char*) "Asia/Qatar" , 0x02C28F }, - { (char*) "Asia/Qostanay" , 0x02C333 }, - { (char*) "Asia/Qyzylorda" , 0x02C5C9 }, - { (char*) "Asia/Rangoon" , 0x02C862 }, - { (char*) "Asia/Riyadh" , 0x02C929 }, - { (char*) "Asia/Saigon" , 0x02C9BA }, - { (char*) "Asia/Sakhalin" , 0x02CAB2 }, - { (char*) "Asia/Samarkand" , 0x02CDC9 }, - { (char*) "Asia/Seoul" , 0x02CF54 }, - { (char*) "Asia/Shanghai" , 0x02D0FF }, - { (char*) "Asia/Singapore" , 0x02D2A0 }, - { (char*) "Asia/Srednekolymsk" , 0x02D3AC }, - { (char*) "Asia/Taipei" , 0x02D6BC }, - { (char*) "Asia/Tashkent" , 0x02D8C7 }, - { (char*) "Asia/Tbilisi" , 0x02DA52 }, - { (char*) "Asia/Tehran" , 0x02DCD3 }, - { (char*) "Asia/Tel_Aviv" , 0x02E00B }, - { (char*) "Asia/Thimbu" , 0x02E449 }, - { (char*) "Asia/Thimphu" , 0x02E4EF }, - { (char*) "Asia/Tokyo" , 0x02E595 }, - { (char*) "Asia/Tomsk" , 0x02E676 }, - { (char*) "Asia/Ujung_Pandang" , 0x02E981 }, - { (char*) "Asia/Ulaanbaatar" , 0x02EA4B }, - { (char*) "Asia/Ulan_Bator" , 0x02ECB9 }, - { (char*) "Asia/Urumqi" , 0x02EF17 }, - { (char*) "Asia/Ust-Nera" , 0x02EFB5 }, - { (char*) "Asia/Vientiane" , 0x02F2D8 }, - { (char*) "Asia/Vladivostok" , 0x02F3BE }, - { (char*) "Asia/Yakutsk" , 0x02F6C3 }, - { (char*) "Asia/Yangon" , 0x02F9C7 }, - { (char*) "Asia/Yekaterinburg" , 0x02FA8E }, - { (char*) "Asia/Yerevan" , 0x02FDA0 }, - { (char*) "Atlantic/Azores" , 0x030070 }, - { (char*) "Atlantic/Bermuda" , 0x0305FB }, - { (char*) "Atlantic/Canary" , 0x030A07 }, - { (char*) "Atlantic/Cape_Verde" , 0x030BFF }, - { (char*) "Atlantic/Faeroe" , 0x030CBA }, - { (char*) "Atlantic/Faroe" , 0x030E7F }, - { (char*) "Atlantic/Jan_Mayen" , 0x031044 }, - { (char*) "Atlantic/Madeira" , 0x031311 }, - { (char*) "Atlantic/Reykjavik" , 0x031888 }, - { (char*) "Atlantic/South_Georgia" , 0x031B85 }, - { (char*) "Atlantic/St_Helena" , 0x031C15 }, - { (char*) "Atlantic/Stanley" , 0x031CB6 }, - { (char*) "Australia/ACT" , 0x031FD7 }, - { (char*) "Australia/Adelaide" , 0x03236B }, - { (char*) "Australia/Brisbane" , 0x03271F }, - { (char*) "Australia/Broken_Hill" , 0x032863 }, - { (char*) "Australia/Canberra" , 0x032C38 }, - { (char*) "Australia/Currie" , 0x032FCC }, - { (char*) "Australia/Darwin" , 0x0333C3 }, - { (char*) "Australia/Eucla" , 0x0334CB }, - { (char*) "Australia/Hobart" , 0x03362A }, - { (char*) "Australia/LHI" , 0x033A29 }, - { (char*) "Australia/Lindeman" , 0x033CE9 }, - { (char*) "Australia/Lord_Howe" , 0x033E59 }, - { (char*) "Australia/Melbourne" , 0x034129 }, - { (char*) "Australia/North" , 0x0344C5 }, - { (char*) "Australia/NSW" , 0x0345BB }, - { (char*) "Australia/Perth" , 0x03494F }, - { (char*) "Australia/Queensland" , 0x034AAB }, - { (char*) "Australia/South" , 0x034BD8 }, - { (char*) "Australia/Sydney" , 0x034F7D }, - { (char*) "Australia/Tasmania" , 0x03532D }, - { (char*) "Australia/Victoria" , 0x035724 }, - { (char*) "Australia/West" , 0x035AB8 }, - { (char*) "Australia/Yancowinna" , 0x035BF6 }, - { (char*) "Brazil/Acre" , 0x035FAF }, - { (char*) "Brazil/DeNoronha" , 0x03615D }, - { (char*) "Brazil/East" , 0x03634D }, - { (char*) "Brazil/West" , 0x036711 }, - { (char*) "Canada/Atlantic" , 0x0368B9 }, - { (char*) "Canada/Central" , 0x036F4D }, - { (char*) "Canada/Eastern" , 0x037467 }, - { (char*) "Canada/Mountain" , 0x037B28 }, - { (char*) "Canada/Newfoundland" , 0x037EFE }, - { (char*) "Canada/Pacific" , 0x038660 }, - { (char*) "Canada/Saskatchewan" , 0x038B9E }, - { (char*) "Canada/Yukon" , 0x038E28 }, - { (char*) "CET" , 0x039239 }, - { (char*) "Chile/Continental" , 0x039694 }, - { (char*) "Chile/EasterIsland" , 0x039BEA }, - { (char*) "CST6CDT" , 0x03A08C }, - { (char*) "Cuba" , 0x03A772 }, - { (char*) "EET" , 0x03ABDB }, - { (char*) "Egypt" , 0x03AE91 }, - { (char*) "Eire" , 0x03B3BA }, - { (char*) "EST" , 0x03B99E }, - { (char*) "EST5EDT" , 0x03BA3F }, - { (char*) "Etc/GMT" , 0x03C11B }, - { (char*) "Etc/GMT+0" , 0x03C196 }, - { (char*) "Etc/GMT+1" , 0x03C211 }, - { (char*) "Etc/GMT+10" , 0x03C28E }, - { (char*) "Etc/GMT+11" , 0x03C30C }, - { (char*) "Etc/GMT+12" , 0x03C38A }, - { (char*) "Etc/GMT+2" , 0x03C408 }, - { (char*) "Etc/GMT+3" , 0x03C485 }, - { (char*) "Etc/GMT+4" , 0x03C502 }, - { (char*) "Etc/GMT+5" , 0x03C57F }, - { (char*) "Etc/GMT+6" , 0x03C5FC }, - { (char*) "Etc/GMT+7" , 0x03C679 }, - { (char*) "Etc/GMT+8" , 0x03C6F6 }, - { (char*) "Etc/GMT+9" , 0x03C773 }, - { (char*) "Etc/GMT-0" , 0x03C7F0 }, - { (char*) "Etc/GMT-1" , 0x03C86B }, - { (char*) "Etc/GMT-10" , 0x03C8E9 }, - { (char*) "Etc/GMT-11" , 0x03C968 }, - { (char*) "Etc/GMT-12" , 0x03C9E7 }, - { (char*) "Etc/GMT-13" , 0x03CA66 }, - { (char*) "Etc/GMT-14" , 0x03CAE5 }, - { (char*) "Etc/GMT-2" , 0x03CB64 }, - { (char*) "Etc/GMT-3" , 0x03CBE2 }, - { (char*) "Etc/GMT-4" , 0x03CC60 }, - { (char*) "Etc/GMT-5" , 0x03CCDE }, - { (char*) "Etc/GMT-6" , 0x03CD5C }, - { (char*) "Etc/GMT-7" , 0x03CDDA }, - { (char*) "Etc/GMT-8" , 0x03CE58 }, - { (char*) "Etc/GMT-9" , 0x03CED6 }, - { (char*) "Etc/GMT0" , 0x03CF54 }, - { (char*) "Etc/Greenwich" , 0x03CFCF }, - { (char*) "Etc/UCT" , 0x03D04A }, - { (char*) "Etc/Universal" , 0x03D0C5 }, - { (char*) "Etc/UTC" , 0x03D140 }, - { (char*) "Etc/Zulu" , 0x03D1BB }, - { (char*) "Europe/Amsterdam" , 0x03D236 }, - { (char*) "Europe/Andorra" , 0x03D671 }, - { (char*) "Europe/Astrakhan" , 0x03D802 }, - { (char*) "Europe/Athens" , 0x03DAF6 }, - { (char*) "Europe/Belfast" , 0x03DDAC }, - { (char*) "Europe/Belgrade" , 0x03E3F7 }, - { (char*) "Europe/Berlin" , 0x03E5E1 }, - { (char*) "Europe/Bratislava" , 0x03E8BD }, - { (char*) "Europe/Brussels" , 0x03EB9C }, - { (char*) "Europe/Bucharest" , 0x03EFF7 }, - { (char*) "Europe/Budapest" , 0x03F298 }, - { (char*) "Europe/Busingen" , 0x03F5A2 }, - { (char*) "Europe/Chisinau" , 0x03F7A7 }, - { (char*) "Europe/Copenhagen" , 0x03FAA6 }, - { (char*) "Europe/Dublin" , 0x03FD21 }, - { (char*) "Europe/Gibraltar" , 0x040305 }, - { (char*) "Europe/Guernsey" , 0x0407D5 }, - { (char*) "Europe/Helsinki" , 0x040E2C }, - { (char*) "Europe/Isle_of_Man" , 0x041019 }, - { (char*) "Europe/Istanbul" , 0x041664 }, - { (char*) "Europe/Jersey" , 0x041B20 }, - { (char*) "Europe/Kaliningrad" , 0x042177 }, - { (char*) "Europe/Kiev" , 0x04251F }, - { (char*) "Europe/Kirov" , 0x042759 }, - { (char*) "Europe/Kyiv" , 0x042A52 }, - { (char*) "Europe/Lisbon" , 0x042C9B }, - { (char*) "Europe/Ljubljana" , 0x043271 }, - { (char*) "Europe/London" , 0x04345B }, - { (char*) "Europe/Luxembourg" , 0x043AA6 }, - { (char*) "Europe/Madrid" , 0x043EF1 }, - { (char*) "Europe/Malta" , 0x04428E }, - { (char*) "Europe/Mariehamn" , 0x04463A }, - { (char*) "Europe/Minsk" , 0x044827 }, - { (char*) "Europe/Monaco" , 0x044B5B }, - { (char*) "Europe/Moscow" , 0x044FC1 }, - { (char*) "Europe/Nicosia" , 0x04536D }, - { (char*) "Europe/Oslo" , 0x0455CE }, - { (char*) "Europe/Paris" , 0x04587E }, - { (char*) "Europe/Podgorica" , 0x045CDB }, - { (char*) "Europe/Prague" , 0x045EC5 }, - { (char*) "Europe/Riga" , 0x0461A4 }, - { (char*) "Europe/Rome" , 0x046466 }, - { (char*) "Europe/Samara" , 0x046825 }, - { (char*) "Europe/San_Marino" , 0x046B26 }, - { (char*) "Europe/Sarajevo" , 0x046EE5 }, - { (char*) "Europe/Saratov" , 0x0470CF }, - { (char*) "Europe/Simferopol" , 0x0473C1 }, - { (char*) "Europe/Skopje" , 0x047734 }, - { (char*) "Europe/Sofia" , 0x04791E }, - { (char*) "Europe/Stockholm" , 0x047B7A }, - { (char*) "Europe/Tallinn" , 0x047D77 }, - { (char*) "Europe/Tirane" , 0x048026 }, - { (char*) "Europe/Tiraspol" , 0x04828E }, - { (char*) "Europe/Ulyanovsk" , 0x04858D }, - { (char*) "Europe/Uzhgorod" , 0x0488A3 }, - { (char*) "Europe/Vaduz" , 0x048ADD }, - { (char*) "Europe/Vatican" , 0x048CC7 }, - { (char*) "Europe/Vienna" , 0x049086 }, - { (char*) "Europe/Vilnius" , 0x049324 }, - { (char*) "Europe/Volgograd" , 0x0495D4 }, - { (char*) "Europe/Warsaw" , 0x0498E3 }, - { (char*) "Europe/Zagreb" , 0x049C8A }, - { (char*) "Europe/Zaporozhye" , 0x049E74 }, - { (char*) "Europe/Zurich" , 0x04A0AE }, - { (char*) "Factory" , 0x04A2AB }, - { (char*) "GB" , 0x04A328 }, - { (char*) "GB-Eire" , 0x04A973 }, - { (char*) "GMT" , 0x04AFBE }, - { (char*) "GMT+0" , 0x04B039 }, - { (char*) "GMT-0" , 0x04B0B4 }, - { (char*) "GMT0" , 0x04B12F }, - { (char*) "Greenwich" , 0x04B1AA }, - { (char*) "Hongkong" , 0x04B225 }, - { (char*) "HST" , 0x04B538 }, - { (char*) "Iceland" , 0x04B621 }, - { (char*) "Indian/Antananarivo" , 0x04B6AF }, - { (char*) "Indian/Chagos" , 0x04B75B }, - { (char*) "Indian/Christmas" , 0x04B7FF }, - { (char*) "Indian/Cocos" , 0x04B890 }, - { (char*) "Indian/Comoro" , 0x04B928 }, - { (char*) "Indian/Kerguelen" , 0x04B9B7 }, - { (char*) "Indian/Mahe" , 0x04BA48 }, - { (char*) "Indian/Maldives" , 0x04BAD9 }, - { (char*) "Indian/Mauritius" , 0x04BB7D }, - { (char*) "Indian/Mayotte" , 0x04BC3C }, - { (char*) "Indian/Reunion" , 0x04BCCB }, - { (char*) "Iran" , 0x04BD5C }, - { (char*) "Israel" , 0x04C094 }, - { (char*) "Jamaica" , 0x04C4D2 }, - { (char*) "Japan" , 0x04C631 }, - { (char*) "Kwajalein" , 0x04C712 }, - { (char*) "Libya" , 0x04C7F9 }, - { (char*) "MET" , 0x04C9B4 }, - { (char*) "Mexico/BajaNorte" , 0x04CE0F }, - { (char*) "Mexico/BajaSur" , 0x04D252 }, - { (char*) "Mexico/General" , 0x04D510 }, - { (char*) "MST" , 0x04D821 }, - { (char*) "MST7MDT" , 0x04D91D }, - { (char*) "Navajo" , 0x04DD3B }, - { (char*) "NZ" , 0x04E159 }, - { (char*) "NZ-CHAT" , 0x04E578 }, - { (char*) "Pacific/Apia" , 0x04E8AC }, - { (char*) "Pacific/Auckland" , 0x04EA4F }, - { (char*) "Pacific/Bougainville" , 0x04EE81 }, - { (char*) "Pacific/Chatham" , 0x04EF62 }, - { (char*) "Pacific/Chuuk" , 0x04F2A5 }, - { (char*) "Pacific/Easter" , 0x04F383 }, - { (char*) "Pacific/Efate" , 0x04F832 }, - { (char*) "Pacific/Enderbury" , 0x04F994 }, - { (char*) "Pacific/Fakaofo" , 0x04FA4C }, - { (char*) "Pacific/Fiji" , 0x04FAF1 }, - { (char*) "Pacific/Funafuti" , 0x04FC89 }, - { (char*) "Pacific/Galapagos" , 0x04FD1B }, - { (char*) "Pacific/Gambier" , 0x04FDE7 }, - { (char*) "Pacific/Guadalcanal" , 0x04FE86 }, - { (char*) "Pacific/Guam" , 0x04FF18 }, - { (char*) "Pacific/Honolulu" , 0x050082 }, - { (char*) "Pacific/Johnston" , 0x050171 }, - { (char*) "Pacific/Kanton" , 0x05025A }, - { (char*) "Pacific/Kiritimati" , 0x050321 }, - { (char*) "Pacific/Kosrae" , 0x0503E7 }, - { (char*) "Pacific/Kwajalein" , 0x0504EB }, - { (char*) "Pacific/Majuro" , 0x0505DB }, - { (char*) "Pacific/Marquesas" , 0x0506D9 }, - { (char*) "Pacific/Midway" , 0x050781 }, - { (char*) "Pacific/Nauru" , 0x050844 }, - { (char*) "Pacific/Niue" , 0x050907 }, - { (char*) "Pacific/Norfolk" , 0x0509AD }, - { (char*) "Pacific/Noumea" , 0x050AA6 }, - { (char*) "Pacific/Pago_Pago" , 0x050B78 }, - { (char*) "Pacific/Palau" , 0x050C16 }, - { (char*) "Pacific/Pitcairn" , 0x050CB6 }, - { (char*) "Pacific/Pohnpei" , 0x050D5B }, - { (char*) "Pacific/Ponape" , 0x050E4B }, - { (char*) "Pacific/Port_Moresby" , 0x050EDD }, - { (char*) "Pacific/Rarotonga" , 0x050F9B }, - { (char*) "Pacific/Saipan" , 0x05113D }, - { (char*) "Pacific/Samoa" , 0x05129E }, - { (char*) "Pacific/Tahiti" , 0x05133C }, - { (char*) "Pacific/Tarawa" , 0x0513DC }, - { (char*) "Pacific/Tongatapu" , 0x05147D }, - { (char*) "Pacific/Truk" , 0x051576 }, - { (char*) "Pacific/Wake" , 0x05161C }, - { (char*) "Pacific/Wallis" , 0x0516B9 }, - { (char*) "Pacific/Yap" , 0x05174B }, - { (char*) "Poland" , 0x0517F1 }, - { (char*) "Portugal" , 0x051B98 }, - { (char*) "PRC" , 0x05215B }, - { (char*) "PST8PDT" , 0x0522F0 }, - { (char*) "ROC" , 0x05280A }, - { (char*) "ROK" , 0x052A15 }, - { (char*) "Singapore" , 0x052BC0 }, - { (char*) "Turkey" , 0x052CCC }, - { (char*) "UCT" , 0x053188 }, - { (char*) "Universal" , 0x053203 }, - { (char*) "US/Alaska" , 0x05327E }, - { (char*) "US/Aleutian" , 0x05365B }, - { (char*) "US/Arizona" , 0x053A30 }, - { (char*) "US/Central" , 0x053B2C }, - { (char*) "US/East-Indiana" , 0x054212 }, - { (char*) "US/Eastern" , 0x054431 }, - { (char*) "US/Hawaii" , 0x054B0D }, - { (char*) "US/Indiana-Starke" , 0x054BF6 }, - { (char*) "US/Michigan" , 0x054FFA }, - { (char*) "US/Mountain" , 0x055389 }, - { (char*) "US/Pacific" , 0x0557A7 }, - { (char*) "US/Samoa" , 0x055CC1 }, - { (char*) "UTC" , 0x055D5F }, - { (char*) "W-SU" , 0x055DDA }, - { (char*) "WET" , 0x056172 }, - { (char*) "Zulu" , 0x056735 }, + { (char*) "America/Coyhaique" , 0x00B238 }, + { (char*) "America/Creston" , 0x00B7A2 }, + { (char*) "America/Cuiaba" , 0x00B85E }, + { (char*) "America/Curacao" , 0x00BC1B }, + { (char*) "America/Danmarkshavn" , 0x00BCBE }, + { (char*) "America/Dawson" , 0x00BEA3 }, + { (char*) "America/Dawson_Creek" , 0x00C2C6 }, + { (char*) "America/Denver" , 0x00C59D }, + { (char*) "America/Detroit" , 0x00C9D0 }, + { (char*) "America/Dominica" , 0x00CD78 }, + { (char*) "America/Edmonton" , 0x00CE06 }, + { (char*) "America/Eirunepe" , 0x00D1FE }, + { (char*) "America/El_Salvador" , 0x00D3CD }, + { (char*) "America/Ensenada" , 0x00D489 }, + { (char*) "America/Fort_Nelson" , 0x00D8CC }, + { (char*) "America/Fort_Wayne" , 0x00DE94 }, + { (char*) "America/Fortaleza" , 0x00E0B3 }, + { (char*) "America/Glace_Bay" , 0x00E2C9 }, + { (char*) "America/Godthab" , 0x00E660 }, + { (char*) "America/Goose_Bay" , 0x00EA31 }, + { (char*) "America/Grand_Turk" , 0x00F089 }, + { (char*) "America/Grenada" , 0x00F3EA }, + { (char*) "America/Guadeloupe" , 0x00F478 }, + { (char*) "America/Guatemala" , 0x00F506 }, + { (char*) "America/Guayaquil" , 0x00F5E6 }, + { (char*) "America/Guyana" , 0x00F6B7 }, + { (char*) "America/Halifax" , 0x00F778 }, + { (char*) "America/Havana" , 0x00FE2A }, + { (char*) "America/Hermosillo" , 0x010293 }, + { (char*) "America/Indiana/Indianapolis" , 0x0103A7 }, + { (char*) "America/Indiana/Knox" , 0x0105DF }, + { (char*) "America/Indiana/Marengo" , 0x0109F8 }, + { (char*) "America/Indiana/Petersburg" , 0x010C52 }, + { (char*) "America/Indiana/Tell_City" , 0x010F1C }, + { (char*) "America/Indiana/Vevay" , 0x011146 }, + { (char*) "America/Indiana/Vincennes" , 0x0112DD }, + { (char*) "America/Indiana/Winamac" , 0x011533 }, + { (char*) "America/Indianapolis" , 0x0117B0 }, + { (char*) "America/Inuvik" , 0x0119CF }, + { (char*) "America/Iqaluit" , 0x011D20 }, + { (char*) "America/Jamaica" , 0x01209C }, + { (char*) "America/Jujuy" , 0x0121FB }, + { (char*) "America/Juneau" , 0x0124B9 }, + { (char*) "America/Kentucky/Louisville" , 0x01289F }, + { (char*) "America/Kentucky/Monticello" , 0x012DA3 }, + { (char*) "America/Knox_IN" , 0x01318F }, + { (char*) "America/Kralendijk" , 0x013593 }, + { (char*) "America/La_Paz" , 0x013650 }, + { (char*) "America/Lima" , 0x013706 }, + { (char*) "America/Los_Angeles" , 0x01382D }, + { (char*) "America/Louisville" , 0x013D4E }, + { (char*) "America/Lower_Princes" , 0x014234 }, + { (char*) "America/Maceio" , 0x0142F1 }, + { (char*) "America/Managua" , 0x014503 }, + { (char*) "America/Manaus" , 0x014636 }, + { (char*) "America/Marigot" , 0x0147ED }, + { (char*) "America/Martinique" , 0x0148AA }, + { (char*) "America/Matamoros" , 0x014968 }, + { (char*) "America/Mazatlan" , 0x014B55 }, + { (char*) "America/Mendoza" , 0x014E45 }, + { (char*) "America/Menominee" , 0x015115 }, + { (char*) "America/Merida" , 0x0154D5 }, + { (char*) "America/Metlakatla" , 0x015780 }, + { (char*) "America/Mexico_City" , 0x0159ED }, + { (char*) "America/Miquelon" , 0x015D0C }, + { (char*) "America/Moncton" , 0x015F3E }, + { (char*) "America/Monterrey" , 0x016537 }, + { (char*) "America/Montevideo" , 0x01683E }, + { (char*) "America/Montreal" , 0x016C13 }, + { (char*) "America/Montserrat" , 0x0172D4 }, + { (char*) "America/Nassau" , 0x017362 }, + { (char*) "America/New_York" , 0x01775C }, + { (char*) "America/Nipigon" , 0x017E4C }, + { (char*) "America/Nome" , 0x01850D }, + { (char*) "America/Noronha" , 0x0188F5 }, + { (char*) "America/North_Dakota/Beulah" , 0x018AF5 }, + { (char*) "America/North_Dakota/Center" , 0x018F29 }, + { (char*) "America/North_Dakota/New_Salem" , 0x019328 }, + { (char*) "America/Nuuk" , 0x01972D }, + { (char*) "America/Ojinaga" , 0x019B0F }, + { (char*) "America/Panama" , 0x019E05 }, + { (char*) "America/Pangnirtung" , 0x019EA6 }, + { (char*) "America/Paramaribo" , 0x01A209 }, + { (char*) "America/Phoenix" , 0x01A2D0 }, + { (char*) "America/Port-au-Prince" , 0x01A3E4 }, + { (char*) "America/Port_of_Spain" , 0x01A625 }, + { (char*) "America/Porto_Acre" , 0x01A6B3 }, + { (char*) "America/Porto_Velho" , 0x01A861 }, + { (char*) "America/Puerto_Rico" , 0x01A9FF }, + { (char*) "America/Punta_Arenas" , 0x01AABC }, + { (char*) "America/Rainy_River" , 0x01AF9B }, + { (char*) "America/Rankin_Inlet" , 0x01B4B5 }, + { (char*) "America/Recife" , 0x01B7FE }, + { (char*) "America/Regina" , 0x01B9F8 }, + { (char*) "America/Resolute" , 0x01BC97 }, + { (char*) "America/Rio_Branco" , 0x01BFE1 }, + { (char*) "America/Rosario" , 0x01C193 }, + { (char*) "America/Santa_Isabel" , 0x01C463 }, + { (char*) "America/Santarem" , 0x01C8A6 }, + { (char*) "America/Santiago" , 0x01CA56 }, + { (char*) "America/Santo_Domingo" , 0x01CFB9 }, + { (char*) "America/Sao_Paulo" , 0x01D102 }, + { (char*) "America/Scoresbysund" , 0x01D4FC }, + { (char*) "America/Shiprock" , 0x01D8FD }, + { (char*) "America/Sitka" , 0x01DD1B }, + { (char*) "America/St_Barthelemy" , 0x01E0F6 }, + { (char*) "America/St_Johns" , 0x01E1B3 }, + { (char*) "America/St_Kitts" , 0x01E930 }, + { (char*) "America/St_Lucia" , 0x01E9BE }, + { (char*) "America/St_Thomas" , 0x01EA5F }, + { (char*) "America/St_Vincent" , 0x01EAED }, + { (char*) "America/Swift_Current" , 0x01EB8E }, + { (char*) "America/Tegucigalpa" , 0x01ED1C }, + { (char*) "America/Thule" , 0x01EDEA }, + { (char*) "America/Thunder_Bay" , 0x01EFCB }, + { (char*) "America/Tijuana" , 0x01F68C }, + { (char*) "America/Toronto" , 0x01FADE }, + { (char*) "America/Tortola" , 0x0201BD }, + { (char*) "America/Vancouver" , 0x02024B }, + { (char*) "America/Virgin" , 0x0207A2 }, + { (char*) "America/Whitehorse" , 0x02085F }, + { (char*) "America/Winnipeg" , 0x020C82 }, + { (char*) "America/Yakutat" , 0x0211B9 }, + { (char*) "America/Yellowknife" , 0x021587 }, + { (char*) "Antarctica/Casey" , 0x02195D }, + { (char*) "Antarctica/Davis" , 0x021A8D }, + { (char*) "Antarctica/DumontDUrville" , 0x021B63 }, + { (char*) "Antarctica/Macquarie" , 0x021C17 }, + { (char*) "Antarctica/Mawson" , 0x022003 }, + { (char*) "Antarctica/McMurdo" , 0x0220AD }, + { (char*) "Antarctica/Palmer" , 0x0223DF }, + { (char*) "Antarctica/Rothera" , 0x022768 }, + { (char*) "Antarctica/South_Pole" , 0x0227FF }, + { (char*) "Antarctica/Syowa" , 0x022C1E }, + { (char*) "Antarctica/Troll" , 0x022CB4 }, + { (char*) "Antarctica/Vostok" , 0x022D63 }, + { (char*) "Arctic/Longyearbyen" , 0x022E1F }, + { (char*) "Asia/Aden" , 0x0230EC }, + { (char*) "Asia/Almaty" , 0x02317D }, + { (char*) "Asia/Amman" , 0x023405 }, + { (char*) "Asia/Anadyr" , 0x0237B1 }, + { (char*) "Asia/Aqtau" , 0x023AB7 }, + { (char*) "Asia/Aqtobe" , 0x023D36 }, + { (char*) "Asia/Ashgabat" , 0x023FB6 }, + { (char*) "Asia/Ashkhabad" , 0x024139 }, + { (char*) "Asia/Atyrau" , 0x0242BC }, + { (char*) "Asia/Baghdad" , 0x024545 }, + { (char*) "Asia/Bahrain" , 0x0247C7 }, + { (char*) "Asia/Baku" , 0x024880 }, + { (char*) "Asia/Bangkok" , 0x024B74 }, + { (char*) "Asia/Barnaul" , 0x024C18 }, + { (char*) "Asia/Beirut" , 0x024F23 }, + { (char*) "Asia/Bishkek" , 0x02520B }, + { (char*) "Asia/Brunei" , 0x025481 }, + { (char*) "Asia/Calcutta" , 0x025527 }, + { (char*) "Asia/Chita" , 0x02560F }, + { (char*) "Asia/Choibalsan" , 0x02591D }, + { (char*) "Asia/Chongqing" , 0x025B7B }, + { (char*) "Asia/Chungking" , 0x025D10 }, + { (char*) "Asia/Colombo" , 0x025EA5 }, + { (char*) "Asia/Dacca" , 0x025FA8 }, + { (char*) "Asia/Damascus" , 0x02609B }, + { (char*) "Asia/Dhaka" , 0x026579 }, + { (char*) "Asia/Dili" , 0x02666C }, + { (char*) "Asia/Dubai" , 0x026722 }, + { (char*) "Asia/Dushanbe" , 0x0267B3 }, + { (char*) "Asia/Famagusta" , 0x02692D }, + { (char*) "Asia/Gaza" , 0x026CF4 }, + { (char*) "Asia/Harbin" , 0x027890 }, + { (char*) "Asia/Hebron" , 0x027A25 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x0285D2 }, + { (char*) "Asia/Hong_Kong" , 0x0286CA }, + { (char*) "Asia/Hovd" , 0x0289DD }, + { (char*) "Asia/Irkutsk" , 0x028C51 }, + { (char*) "Asia/Istanbul" , 0x028F6F }, + { (char*) "Asia/Jakarta" , 0x02942B }, + { (char*) "Asia/Jayapura" , 0x02953C }, + { (char*) "Asia/Jerusalem" , 0x029629 }, + { (char*) "Asia/Kabul" , 0x029A67 }, + { (char*) "Asia/Kamchatka" , 0x029B12 }, + { (char*) "Asia/Karachi" , 0x029E07 }, + { (char*) "Asia/Kashgar" , 0x029F1D }, + { (char*) "Asia/Kathmandu" , 0x029FAE }, + { (char*) "Asia/Katmandu" , 0x02A05B }, + { (char*) "Asia/Khandyga" , 0x02A108 }, + { (char*) "Asia/Kolkata" , 0x02A439 }, + { (char*) "Asia/Krasnoyarsk" , 0x02A521 }, + { (char*) "Asia/Kuala_Lumpur" , 0x02A82B }, + { (char*) "Asia/Kuching" , 0x02A94B }, + { (char*) "Asia/Kuwait" , 0x02AAA5 }, + { (char*) "Asia/Macao" , 0x02AB36 }, + { (char*) "Asia/Macau" , 0x02AE59 }, + { (char*) "Asia/Magadan" , 0x02B17C }, + { (char*) "Asia/Makassar" , 0x02B487 }, + { (char*) "Asia/Manila" , 0x02B59A }, + { (char*) "Asia/Muscat" , 0x02B6B8 }, + { (char*) "Asia/Nicosia" , 0x02B749 }, + { (char*) "Asia/Novokuznetsk" , 0x02B9B8 }, + { (char*) "Asia/Novosibirsk" , 0x02BCAB }, + { (char*) "Asia/Omsk" , 0x02BFBC }, + { (char*) "Asia/Oral" , 0x02C2BA }, + { (char*) "Asia/Phnom_Penh" , 0x02C546 }, + { (char*) "Asia/Pontianak" , 0x02C61A }, + { (char*) "Asia/Pyongyang" , 0x02C733 }, + { (char*) "Asia/Qatar" , 0x02C7F6 }, + { (char*) "Asia/Qostanay" , 0x02C89A }, + { (char*) "Asia/Qyzylorda" , 0x02CB30 }, + { (char*) "Asia/Rangoon" , 0x02CDC9 }, + { (char*) "Asia/Riyadh" , 0x02CE90 }, + { (char*) "Asia/Saigon" , 0x02CF21 }, + { (char*) "Asia/Sakhalin" , 0x02D019 }, + { (char*) "Asia/Samarkand" , 0x02D330 }, + { (char*) "Asia/Seoul" , 0x02D4BB }, + { (char*) "Asia/Shanghai" , 0x02D666 }, + { (char*) "Asia/Singapore" , 0x02D807 }, + { (char*) "Asia/Srednekolymsk" , 0x02D913 }, + { (char*) "Asia/Taipei" , 0x02DC23 }, + { (char*) "Asia/Tashkent" , 0x02DE2E }, + { (char*) "Asia/Tbilisi" , 0x02DFB9 }, + { (char*) "Asia/Tehran" , 0x02E23A }, + { (char*) "Asia/Tel_Aviv" , 0x02E572 }, + { (char*) "Asia/Thimbu" , 0x02E9B0 }, + { (char*) "Asia/Thimphu" , 0x02EA56 }, + { (char*) "Asia/Tokyo" , 0x02EAFC }, + { (char*) "Asia/Tomsk" , 0x02EBDD }, + { (char*) "Asia/Ujung_Pandang" , 0x02EEE8 }, + { (char*) "Asia/Ulaanbaatar" , 0x02EFB2 }, + { (char*) "Asia/Ulan_Bator" , 0x02F220 }, + { (char*) "Asia/Urumqi" , 0x02F47E }, + { (char*) "Asia/Ust-Nera" , 0x02F51C }, + { (char*) "Asia/Vientiane" , 0x02F83F }, + { (char*) "Asia/Vladivostok" , 0x02F925 }, + { (char*) "Asia/Yakutsk" , 0x02FC2A }, + { (char*) "Asia/Yangon" , 0x02FF2E }, + { (char*) "Asia/Yekaterinburg" , 0x02FFF5 }, + { (char*) "Asia/Yerevan" , 0x030307 }, + { (char*) "Atlantic/Azores" , 0x0305D7 }, + { (char*) "Atlantic/Bermuda" , 0x030B62 }, + { (char*) "Atlantic/Canary" , 0x030F6E }, + { (char*) "Atlantic/Cape_Verde" , 0x031166 }, + { (char*) "Atlantic/Faeroe" , 0x031221 }, + { (char*) "Atlantic/Faroe" , 0x0313E6 }, + { (char*) "Atlantic/Jan_Mayen" , 0x0315AB }, + { (char*) "Atlantic/Madeira" , 0x031878 }, + { (char*) "Atlantic/Reykjavik" , 0x031DEF }, + { (char*) "Atlantic/South_Georgia" , 0x0320EC }, + { (char*) "Atlantic/St_Helena" , 0x03217C }, + { (char*) "Atlantic/Stanley" , 0x03221D }, + { (char*) "Australia/ACT" , 0x03253E }, + { (char*) "Australia/Adelaide" , 0x0328D2 }, + { (char*) "Australia/Brisbane" , 0x032C86 }, + { (char*) "Australia/Broken_Hill" , 0x032DCA }, + { (char*) "Australia/Canberra" , 0x03319F }, + { (char*) "Australia/Currie" , 0x033533 }, + { (char*) "Australia/Darwin" , 0x03392A }, + { (char*) "Australia/Eucla" , 0x033A32 }, + { (char*) "Australia/Hobart" , 0x033B91 }, + { (char*) "Australia/LHI" , 0x033F90 }, + { (char*) "Australia/Lindeman" , 0x034250 }, + { (char*) "Australia/Lord_Howe" , 0x0343C0 }, + { (char*) "Australia/Melbourne" , 0x034690 }, + { (char*) "Australia/North" , 0x034A2C }, + { (char*) "Australia/NSW" , 0x034B22 }, + { (char*) "Australia/Perth" , 0x034EB6 }, + { (char*) "Australia/Queensland" , 0x035012 }, + { (char*) "Australia/South" , 0x03513F }, + { (char*) "Australia/Sydney" , 0x0354E4 }, + { (char*) "Australia/Tasmania" , 0x035894 }, + { (char*) "Australia/Victoria" , 0x035C8B }, + { (char*) "Australia/West" , 0x03601F }, + { (char*) "Australia/Yancowinna" , 0x03615D }, + { (char*) "Brazil/Acre" , 0x036516 }, + { (char*) "Brazil/DeNoronha" , 0x0366C4 }, + { (char*) "Brazil/East" , 0x0368B4 }, + { (char*) "Brazil/West" , 0x036C78 }, + { (char*) "Canada/Atlantic" , 0x036E20 }, + { (char*) "Canada/Central" , 0x0374B4 }, + { (char*) "Canada/Eastern" , 0x0379CE }, + { (char*) "Canada/Mountain" , 0x03808F }, + { (char*) "Canada/Newfoundland" , 0x038465 }, + { (char*) "Canada/Pacific" , 0x038BC7 }, + { (char*) "Canada/Saskatchewan" , 0x039105 }, + { (char*) "Canada/Yukon" , 0x03938F }, + { (char*) "CET" , 0x0397A0 }, + { (char*) "Chile/Continental" , 0x039BFB }, + { (char*) "Chile/EasterIsland" , 0x03A151 }, + { (char*) "CST6CDT" , 0x03A5F3 }, + { (char*) "Cuba" , 0x03ACD9 }, + { (char*) "EET" , 0x03B142 }, + { (char*) "Egypt" , 0x03B3F8 }, + { (char*) "Eire" , 0x03B921 }, + { (char*) "EST" , 0x03BF05 }, + { (char*) "EST5EDT" , 0x03BFA6 }, + { (char*) "Etc/GMT" , 0x03C682 }, + { (char*) "Etc/GMT+0" , 0x03C6FD }, + { (char*) "Etc/GMT+1" , 0x03C778 }, + { (char*) "Etc/GMT+10" , 0x03C7F5 }, + { (char*) "Etc/GMT+11" , 0x03C873 }, + { (char*) "Etc/GMT+12" , 0x03C8F1 }, + { (char*) "Etc/GMT+2" , 0x03C96F }, + { (char*) "Etc/GMT+3" , 0x03C9EC }, + { (char*) "Etc/GMT+4" , 0x03CA69 }, + { (char*) "Etc/GMT+5" , 0x03CAE6 }, + { (char*) "Etc/GMT+6" , 0x03CB63 }, + { (char*) "Etc/GMT+7" , 0x03CBE0 }, + { (char*) "Etc/GMT+8" , 0x03CC5D }, + { (char*) "Etc/GMT+9" , 0x03CCDA }, + { (char*) "Etc/GMT-0" , 0x03CD57 }, + { (char*) "Etc/GMT-1" , 0x03CDD2 }, + { (char*) "Etc/GMT-10" , 0x03CE50 }, + { (char*) "Etc/GMT-11" , 0x03CECF }, + { (char*) "Etc/GMT-12" , 0x03CF4E }, + { (char*) "Etc/GMT-13" , 0x03CFCD }, + { (char*) "Etc/GMT-14" , 0x03D04C }, + { (char*) "Etc/GMT-2" , 0x03D0CB }, + { (char*) "Etc/GMT-3" , 0x03D149 }, + { (char*) "Etc/GMT-4" , 0x03D1C7 }, + { (char*) "Etc/GMT-5" , 0x03D245 }, + { (char*) "Etc/GMT-6" , 0x03D2C3 }, + { (char*) "Etc/GMT-7" , 0x03D341 }, + { (char*) "Etc/GMT-8" , 0x03D3BF }, + { (char*) "Etc/GMT-9" , 0x03D43D }, + { (char*) "Etc/GMT0" , 0x03D4BB }, + { (char*) "Etc/Greenwich" , 0x03D536 }, + { (char*) "Etc/UCT" , 0x03D5B1 }, + { (char*) "Etc/Universal" , 0x03D62C }, + { (char*) "Etc/UTC" , 0x03D6A7 }, + { (char*) "Etc/Zulu" , 0x03D722 }, + { (char*) "Europe/Amsterdam" , 0x03D79D }, + { (char*) "Europe/Andorra" , 0x03DBD8 }, + { (char*) "Europe/Astrakhan" , 0x03DD69 }, + { (char*) "Europe/Athens" , 0x03E05D }, + { (char*) "Europe/Belfast" , 0x03E313 }, + { (char*) "Europe/Belgrade" , 0x03E95E }, + { (char*) "Europe/Berlin" , 0x03EB48 }, + { (char*) "Europe/Bratislava" , 0x03EE24 }, + { (char*) "Europe/Brussels" , 0x03F103 }, + { (char*) "Europe/Bucharest" , 0x03F55E }, + { (char*) "Europe/Budapest" , 0x03F7FF }, + { (char*) "Europe/Busingen" , 0x03FB09 }, + { (char*) "Europe/Chisinau" , 0x03FD0E }, + { (char*) "Europe/Copenhagen" , 0x04000D }, + { (char*) "Europe/Dublin" , 0x040288 }, + { (char*) "Europe/Gibraltar" , 0x04086C }, + { (char*) "Europe/Guernsey" , 0x040D3C }, + { (char*) "Europe/Helsinki" , 0x041393 }, + { (char*) "Europe/Isle_of_Man" , 0x041580 }, + { (char*) "Europe/Istanbul" , 0x041BCB }, + { (char*) "Europe/Jersey" , 0x042087 }, + { (char*) "Europe/Kaliningrad" , 0x0426DE }, + { (char*) "Europe/Kiev" , 0x042A86 }, + { (char*) "Europe/Kirov" , 0x042CC0 }, + { (char*) "Europe/Kyiv" , 0x042FB9 }, + { (char*) "Europe/Lisbon" , 0x043202 }, + { (char*) "Europe/Ljubljana" , 0x0437D8 }, + { (char*) "Europe/London" , 0x0439C2 }, + { (char*) "Europe/Luxembourg" , 0x04400D }, + { (char*) "Europe/Madrid" , 0x044458 }, + { (char*) "Europe/Malta" , 0x0447F5 }, + { (char*) "Europe/Mariehamn" , 0x044BA1 }, + { (char*) "Europe/Minsk" , 0x044D8E }, + { (char*) "Europe/Monaco" , 0x0450C2 }, + { (char*) "Europe/Moscow" , 0x045528 }, + { (char*) "Europe/Nicosia" , 0x0458D4 }, + { (char*) "Europe/Oslo" , 0x045B35 }, + { (char*) "Europe/Paris" , 0x045DE5 }, + { (char*) "Europe/Podgorica" , 0x046242 }, + { (char*) "Europe/Prague" , 0x04642C }, + { (char*) "Europe/Riga" , 0x04670B }, + { (char*) "Europe/Rome" , 0x0469CD }, + { (char*) "Europe/Samara" , 0x046D8C }, + { (char*) "Europe/San_Marino" , 0x04708D }, + { (char*) "Europe/Sarajevo" , 0x04744C }, + { (char*) "Europe/Saratov" , 0x047636 }, + { (char*) "Europe/Simferopol" , 0x047928 }, + { (char*) "Europe/Skopje" , 0x047C9B }, + { (char*) "Europe/Sofia" , 0x047E85 }, + { (char*) "Europe/Stockholm" , 0x0480E1 }, + { (char*) "Europe/Tallinn" , 0x0482DE }, + { (char*) "Europe/Tirane" , 0x04858D }, + { (char*) "Europe/Tiraspol" , 0x0487F5 }, + { (char*) "Europe/Ulyanovsk" , 0x048AF4 }, + { (char*) "Europe/Uzhgorod" , 0x048E0A }, + { (char*) "Europe/Vaduz" , 0x049044 }, + { (char*) "Europe/Vatican" , 0x04922E }, + { (char*) "Europe/Vienna" , 0x0495ED }, + { (char*) "Europe/Vilnius" , 0x04988B }, + { (char*) "Europe/Volgograd" , 0x049B3B }, + { (char*) "Europe/Warsaw" , 0x049E4A }, + { (char*) "Europe/Zagreb" , 0x04A1F1 }, + { (char*) "Europe/Zaporozhye" , 0x04A3DB }, + { (char*) "Europe/Zurich" , 0x04A615 }, + { (char*) "Factory" , 0x04A812 }, + { (char*) "GB" , 0x04A88F }, + { (char*) "GB-Eire" , 0x04AEDA }, + { (char*) "GMT" , 0x04B525 }, + { (char*) "GMT+0" , 0x04B5A0 }, + { (char*) "GMT-0" , 0x04B61B }, + { (char*) "GMT0" , 0x04B696 }, + { (char*) "Greenwich" , 0x04B711 }, + { (char*) "Hongkong" , 0x04B78C }, + { (char*) "HST" , 0x04BA9F }, + { (char*) "Iceland" , 0x04BB88 }, + { (char*) "Indian/Antananarivo" , 0x04BC16 }, + { (char*) "Indian/Chagos" , 0x04BCC2 }, + { (char*) "Indian/Christmas" , 0x04BD66 }, + { (char*) "Indian/Cocos" , 0x04BDF7 }, + { (char*) "Indian/Comoro" , 0x04BE8F }, + { (char*) "Indian/Kerguelen" , 0x04BF1E }, + { (char*) "Indian/Mahe" , 0x04BFAF }, + { (char*) "Indian/Maldives" , 0x04C040 }, + { (char*) "Indian/Mauritius" , 0x04C0E4 }, + { (char*) "Indian/Mayotte" , 0x04C1A3 }, + { (char*) "Indian/Reunion" , 0x04C232 }, + { (char*) "Iran" , 0x04C2C3 }, + { (char*) "Israel" , 0x04C5FB }, + { (char*) "Jamaica" , 0x04CA39 }, + { (char*) "Japan" , 0x04CB98 }, + { (char*) "Kwajalein" , 0x04CC79 }, + { (char*) "Libya" , 0x04CD60 }, + { (char*) "MET" , 0x04CF1B }, + { (char*) "Mexico/BajaNorte" , 0x04D376 }, + { (char*) "Mexico/BajaSur" , 0x04D7B9 }, + { (char*) "Mexico/General" , 0x04DA77 }, + { (char*) "MST" , 0x04DD88 }, + { (char*) "MST7MDT" , 0x04DE84 }, + { (char*) "Navajo" , 0x04E2A2 }, + { (char*) "NZ" , 0x04E6C0 }, + { (char*) "NZ-CHAT" , 0x04EADF }, + { (char*) "Pacific/Apia" , 0x04EE13 }, + { (char*) "Pacific/Auckland" , 0x04EFB6 }, + { (char*) "Pacific/Bougainville" , 0x04F3E8 }, + { (char*) "Pacific/Chatham" , 0x04F4C9 }, + { (char*) "Pacific/Chuuk" , 0x04F80C }, + { (char*) "Pacific/Easter" , 0x04F8EA }, + { (char*) "Pacific/Efate" , 0x04FD99 }, + { (char*) "Pacific/Enderbury" , 0x04FEFB }, + { (char*) "Pacific/Fakaofo" , 0x04FFB3 }, + { (char*) "Pacific/Fiji" , 0x050058 }, + { (char*) "Pacific/Funafuti" , 0x0501F0 }, + { (char*) "Pacific/Galapagos" , 0x050282 }, + { (char*) "Pacific/Gambier" , 0x05034E }, + { (char*) "Pacific/Guadalcanal" , 0x0503ED }, + { (char*) "Pacific/Guam" , 0x05047F }, + { (char*) "Pacific/Honolulu" , 0x0505E9 }, + { (char*) "Pacific/Johnston" , 0x0506D8 }, + { (char*) "Pacific/Kanton" , 0x0507C1 }, + { (char*) "Pacific/Kiritimati" , 0x050888 }, + { (char*) "Pacific/Kosrae" , 0x05094E }, + { (char*) "Pacific/Kwajalein" , 0x050A52 }, + { (char*) "Pacific/Majuro" , 0x050B42 }, + { (char*) "Pacific/Marquesas" , 0x050C40 }, + { (char*) "Pacific/Midway" , 0x050CE8 }, + { (char*) "Pacific/Nauru" , 0x050DAB }, + { (char*) "Pacific/Niue" , 0x050E6E }, + { (char*) "Pacific/Norfolk" , 0x050F14 }, + { (char*) "Pacific/Noumea" , 0x05100D }, + { (char*) "Pacific/Pago_Pago" , 0x0510DF }, + { (char*) "Pacific/Palau" , 0x05117D }, + { (char*) "Pacific/Pitcairn" , 0x05121D }, + { (char*) "Pacific/Pohnpei" , 0x0512C2 }, + { (char*) "Pacific/Ponape" , 0x0513B2 }, + { (char*) "Pacific/Port_Moresby" , 0x051444 }, + { (char*) "Pacific/Rarotonga" , 0x051502 }, + { (char*) "Pacific/Saipan" , 0x0516A4 }, + { (char*) "Pacific/Samoa" , 0x051805 }, + { (char*) "Pacific/Tahiti" , 0x0518A3 }, + { (char*) "Pacific/Tarawa" , 0x051943 }, + { (char*) "Pacific/Tongatapu" , 0x0519E4 }, + { (char*) "Pacific/Truk" , 0x051ADD }, + { (char*) "Pacific/Wake" , 0x051B83 }, + { (char*) "Pacific/Wallis" , 0x051C20 }, + { (char*) "Pacific/Yap" , 0x051CB2 }, + { (char*) "Poland" , 0x051D58 }, + { (char*) "Portugal" , 0x0520FF }, + { (char*) "PRC" , 0x0526C2 }, + { (char*) "PST8PDT" , 0x052857 }, + { (char*) "ROC" , 0x052D71 }, + { (char*) "ROK" , 0x052F7C }, + { (char*) "Singapore" , 0x053127 }, + { (char*) "Turkey" , 0x053233 }, + { (char*) "UCT" , 0x0536EF }, + { (char*) "Universal" , 0x05376A }, + { (char*) "US/Alaska" , 0x0537E5 }, + { (char*) "US/Aleutian" , 0x053BC2 }, + { (char*) "US/Arizona" , 0x053F97 }, + { (char*) "US/Central" , 0x054093 }, + { (char*) "US/East-Indiana" , 0x054779 }, + { (char*) "US/Eastern" , 0x054998 }, + { (char*) "US/Hawaii" , 0x055074 }, + { (char*) "US/Indiana-Starke" , 0x05515D }, + { (char*) "US/Michigan" , 0x055561 }, + { (char*) "US/Mountain" , 0x0558F0 }, + { (char*) "US/Pacific" , 0x055D0E }, + { (char*) "US/Samoa" , 0x056228 }, + { (char*) "UTC" , 0x0562C6 }, + { (char*) "W-SU" , 0x056341 }, + { (char*) "WET" , 0x0566D9 }, + { (char*) "Zulu" , 0x056C9C }, }; -const unsigned char timelib_timezone_db_data_builtin[354224] = { +const unsigned char timelib_timezone_db_data_builtin[355607] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3709,6 +3710,95 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0xFF, +0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, +0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, +0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, +0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, +0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, 0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, +0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, +0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, 0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, +0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x87, 0x40, 0x00, +0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x60, 0x69, 0x40, 0x00, +0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, +0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, +0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x94, 0x40, 0x00, +0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, +0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, +0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, 0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, +0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, +0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, +0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x06, 0xFF, 0xFF, 0xBC, 0x70, +0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, +0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, +0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, +0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, +0x33, 0x0A, 0x00, 0x43, 0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, +0x73, 0x65, 0x6E, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -7899,9 +7989,8 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, -0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, -0x67, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, -0x65, 0x73, +0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, +0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -13146,7 +13235,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -21311,7 +21400,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -24240,7 +24329,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #else -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x0000A0 }, { (char*) "Africa/Addis_Ababa" , 0x0004D0 }, @@ -24340,508 +24429,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x0114AF }, { (char*) "America/Cordoba" , 0x011571 }, { (char*) "America/Costa_Rica" , 0x0119A3 }, - { (char*) "America/Creston" , 0x011AEB }, - { (char*) "America/Cuiaba" , 0x011BD9 }, - { (char*) "America/Curacao" , 0x01216A }, - { (char*) "America/Danmarkshavn" , 0x012230 }, - { (char*) "America/Dawson" , 0x012510 }, - { (char*) "America/Dawson_Creek" , 0x012B7C }, - { (char*) "America/Denver" , 0x012FC2 }, - { (char*) "America/Detroit" , 0x01397F }, - { (char*) "America/Dominica" , 0x01425A }, - { (char*) "America/Edmonton" , 0x0142FA }, - { (char*) "America/Eirunepe" , 0x014C44 }, - { (char*) "America/El_Salvador" , 0x014EE1 }, - { (char*) "America/Ensenada" , 0x014FCD }, - { (char*) "America/Fort_Nelson" , 0x015973 }, - { (char*) "America/Fort_Wayne" , 0x016253 }, - { (char*) "America/Fortaleza" , 0x0168F1 }, - { (char*) "America/Glace_Bay" , 0x016BE1 }, - { (char*) "America/Godthab" , 0x017498 }, - { (char*) "America/Goose_Bay" , 0x017C05 }, - { (char*) "America/Grand_Turk" , 0x0188BB }, - { (char*) "America/Grenada" , 0x018FF1 }, - { (char*) "America/Guadeloupe" , 0x019091 }, - { (char*) "America/Guatemala" , 0x019131 }, - { (char*) "America/Guayaquil" , 0x019255 }, - { (char*) "America/Guyana" , 0x01935B }, - { (char*) "America/Halifax" , 0x01945F }, - { (char*) "America/Havana" , 0x01A1E9 }, - { (char*) "America/Hermosillo" , 0x01AB65 }, - { (char*) "America/Indiana/Indianapolis" , 0x01ACFB }, - { (char*) "America/Indiana/Knox" , 0x01B3B2 }, - { (char*) "America/Indiana/Marengo" , 0x01BD5F }, - { (char*) "America/Indiana/Petersburg" , 0x01C44C }, - { (char*) "America/Indiana/Tell_City" , 0x01CBEB }, - { (char*) "America/Indiana/Vevay" , 0x01D2AF }, - { (char*) "America/Indiana/Vincennes" , 0x01D86B }, - { (char*) "America/Indiana/Winamac" , 0x01DF41 }, - { (char*) "America/Indianapolis" , 0x01E665 }, - { (char*) "America/Inuvik" , 0x01ED03 }, - { (char*) "America/Iqaluit" , 0x01F53D }, - { (char*) "America/Jamaica" , 0x01FDFC }, - { (char*) "America/Jujuy" , 0x01FFEA }, - { (char*) "America/Juneau" , 0x020400 }, - { (char*) "America/Kentucky/Louisville" , 0x020D51 }, - { (char*) "America/Kentucky/Monticello" , 0x02185F }, - { (char*) "America/Knox_IN" , 0x0221BF }, - { (char*) "America/Kralendijk" , 0x022B57 }, - { (char*) "America/La_Paz" , 0x022C59 }, - { (char*) "America/Lima" , 0x022D3F }, - { (char*) "America/Los_Angeles" , 0x022ED3 }, - { (char*) "America/Louisville" , 0x023A0A }, - { (char*) "America/Lower_Princes" , 0x0244FA }, - { (char*) "America/Maceio" , 0x0245FC }, - { (char*) "America/Managua" , 0x0248F2 }, - { (char*) "America/Manaus" , 0x024AAC }, - { (char*) "America/Marigot" , 0x024D15 }, - { (char*) "America/Martinique" , 0x024E17 }, - { (char*) "America/Matamoros" , 0x024F0B }, - { (char*) "America/Mazatlan" , 0x0254CD }, - { (char*) "America/Mendoza" , 0x02592F }, - { (char*) "America/Menominee" , 0x025D61 }, - { (char*) "America/Merida" , 0x02666E }, - { (char*) "America/Metlakatla" , 0x026A77 }, - { (char*) "America/Mexico_City" , 0x027029 }, - { (char*) "America/Miquelon" , 0x027509 }, - { (char*) "America/Moncton" , 0x027B89 }, - { (char*) "America/Monterrey" , 0x0287FF }, - { (char*) "America/Montevideo" , 0x028C9B }, - { (char*) "America/Montreal" , 0x02927F }, - { (char*) "America/Montserrat" , 0x02A031 }, - { (char*) "America/Nassau" , 0x02A0D1 }, - { (char*) "America/New_York" , 0x02AA31 }, - { (char*) "America/Nipigon" , 0x02B831 }, - { (char*) "America/Nome" , 0x02C5E3 }, - { (char*) "America/Noronha" , 0x02CF3B }, - { (char*) "America/North_Dakota/Beulah" , 0x02D215 }, - { (char*) "America/North_Dakota/Center" , 0x02DB92 }, - { (char*) "America/North_Dakota/New_Salem" , 0x02E50F }, - { (char*) "America/Nuuk" , 0x02EE92 }, - { (char*) "America/Ojinaga" , 0x02F610 }, - { (char*) "America/Panama" , 0x02FC2C }, - { (char*) "America/Pangnirtung" , 0x02FCEE }, - { (char*) "America/Paramaribo" , 0x030594 }, - { (char*) "America/Phoenix" , 0x030698 }, - { (char*) "America/Port-au-Prince" , 0x030824 }, - { (char*) "America/Port_of_Spain" , 0x030DCA }, - { (char*) "America/Porto_Acre" , 0x030E6A }, - { (char*) "America/Porto_Velho" , 0x0310DC }, - { (char*) "America/Puerto_Rico" , 0x031322 }, - { (char*) "America/Punta_Arenas" , 0x031424 }, - { (char*) "America/Rainy_River" , 0x031BB2 }, - { (char*) "America/Rankin_Inlet" , 0x0326F2 }, - { (char*) "America/Recife" , 0x032F26 }, - { (char*) "America/Regina" , 0x0331FA }, - { (char*) "America/Resolute" , 0x0335EF }, - { (char*) "America/Rio_Branco" , 0x033E24 }, - { (char*) "America/Rosario" , 0x03409A }, - { (char*) "America/Santa_Isabel" , 0x0344CC }, - { (char*) "America/Santarem" , 0x034E72 }, - { (char*) "America/Santiago" , 0x0350D5 }, - { (char*) "America/Santo_Domingo" , 0x035AC1 }, - { (char*) "America/Sao_Paulo" , 0x035C97 }, - { (char*) "America/Scoresbysund" , 0x03626F }, - { (char*) "America/Shiprock" , 0x036A27 }, - { (char*) "America/Sitka" , 0x0373CF }, - { (char*) "America/St_Barthelemy" , 0x037D07 }, - { (char*) "America/St_Johns" , 0x037E09 }, - { (char*) "America/St_Kitts" , 0x038C77 }, - { (char*) "America/St_Lucia" , 0x038D17 }, - { (char*) "America/St_Thomas" , 0x038DD9 }, - { (char*) "America/St_Vincent" , 0x038E79 }, - { (char*) "America/Swift_Current" , 0x038F3B }, - { (char*) "America/Tegucigalpa" , 0x039189 }, - { (char*) "America/Thule" , 0x039291 }, - { (char*) "America/Thunder_Bay" , 0x039889 }, - { (char*) "America/Tijuana" , 0x03A63B }, - { (char*) "America/Toronto" , 0x03AFF0 }, - { (char*) "America/Tortola" , 0x03BDC0 }, - { (char*) "America/Vancouver" , 0x03BE60 }, - { (char*) "America/Virgin" , 0x03C9D1 }, - { (char*) "America/Whitehorse" , 0x03CAD3 }, - { (char*) "America/Winnipeg" , 0x03D13F }, - { (char*) "America/Yakutat" , 0x03DC9C }, - { (char*) "America/Yellowknife" , 0x03E5B9 }, - { (char*) "Antarctica/Casey" , 0x03EEE1 }, - { (char*) "Antarctica/Davis" , 0x03F099 }, - { (char*) "Antarctica/DumontDUrville" , 0x03F1C5 }, - { (char*) "Antarctica/Macquarie" , 0x03F295 }, - { (char*) "Antarctica/Mawson" , 0x03FB85 }, - { (char*) "Antarctica/McMurdo" , 0x03FC50 }, - { (char*) "Antarctica/Palmer" , 0x04044B }, - { (char*) "Antarctica/Rothera" , 0x0409D9 }, - { (char*) "Antarctica/South_Pole" , 0x040A82 }, - { (char*) "Antarctica/Syowa" , 0x041413 }, - { (char*) "Antarctica/Troll" , 0x0414BB }, - { (char*) "Antarctica/Vostok" , 0x041948 }, - { (char*) "Arctic/Longyearbyen" , 0x041A2F }, - { (char*) "Asia/Aden" , 0x042335 }, - { (char*) "Asia/Almaty" , 0x0423D8 }, - { (char*) "Asia/Amman" , 0x0427CD }, - { (char*) "Asia/Anadyr" , 0x042D72 }, - { (char*) "Asia/Aqtau" , 0x043227 }, - { (char*) "Asia/Aqtobe" , 0x043611 }, - { (char*) "Asia/Ashgabat" , 0x043A0F }, - { (char*) "Asia/Ashkhabad" , 0x043C78 }, - { (char*) "Asia/Atyrau" , 0x043EE1 }, - { (char*) "Asia/Baghdad" , 0x0442D3 }, - { (char*) "Asia/Bahrain" , 0x0446A8 }, - { (char*) "Asia/Baku" , 0x044793 }, - { (char*) "Asia/Bangkok" , 0x044C5C }, - { (char*) "Asia/Barnaul" , 0x044D21 }, - { (char*) "Asia/Beirut" , 0x0451F2 }, - { (char*) "Asia/Bishkek" , 0x045A68 }, - { (char*) "Asia/Brunei" , 0x045E3D }, - { (char*) "Asia/Calcutta" , 0x045F06 }, - { (char*) "Asia/Chita" , 0x04602F }, - { (char*) "Asia/Choibalsan" , 0x046506 }, - { (char*) "Asia/Chongqing" , 0x04687F }, - { (char*) "Asia/Chungking" , 0x046ABC }, - { (char*) "Asia/Colombo" , 0x046CF9 }, - { (char*) "Asia/Dacca" , 0x046E6B }, - { (char*) "Asia/Damascus" , 0x046FBA }, - { (char*) "Asia/Dhaka" , 0x047717 }, - { (char*) "Asia/Dili" , 0x047866 }, - { (char*) "Asia/Dubai" , 0x047973 }, - { (char*) "Asia/Dushanbe" , 0x047A16 }, - { (char*) "Asia/Famagusta" , 0x047C63 }, - { (char*) "Asia/Gaza" , 0x04846A }, - { (char*) "Asia/Harbin" , 0x049384 }, - { (char*) "Asia/Hebron" , 0x0495C1 }, - { (char*) "Asia/Ho_Chi_Minh" , 0x04A4F6 }, - { (char*) "Asia/Hong_Kong" , 0x04A653 }, - { (char*) "Asia/Hovd" , 0x04AB30 }, - { (char*) "Asia/Irkutsk" , 0x04AEBF }, - { (char*) "Asia/Istanbul" , 0x04B3B2 }, - { (char*) "Asia/Jakarta" , 0x04BB4B }, - { (char*) "Asia/Jayapura" , 0x04BCE3 }, - { (char*) "Asia/Jerusalem" , 0x04BE02 }, - { (char*) "Asia/Kabul" , 0x04C762 }, - { (char*) "Asia/Kamchatka" , 0x04C830 }, - { (char*) "Asia/Karachi" , 0x04CCCE }, - { (char*) "Asia/Kashgar" , 0x04CE55 }, - { (char*) "Asia/Kathmandu" , 0x04CEF8 }, - { (char*) "Asia/Katmandu" , 0x04CFCA }, - { (char*) "Asia/Khandyga" , 0x04D09C }, - { (char*) "Asia/Kolkata" , 0x04D5AF }, - { (char*) "Asia/Krasnoyarsk" , 0x04D6D8 }, - { (char*) "Asia/Kuala_Lumpur" , 0x04DBA6 }, - { (char*) "Asia/Kuching" , 0x04DD57 }, - { (char*) "Asia/Kuwait" , 0x04DF46 }, - { (char*) "Asia/Macao" , 0x04DFE9 }, - { (char*) "Asia/Macau" , 0x04E4C0 }, - { (char*) "Asia/Magadan" , 0x04E997 }, - { (char*) "Asia/Makassar" , 0x04EE6B }, - { (char*) "Asia/Manila" , 0x04EFBE }, - { (char*) "Asia/Muscat" , 0x04F170 }, - { (char*) "Asia/Nicosia" , 0x04F213 }, - { (char*) "Asia/Novokuznetsk" , 0x04F9FF }, - { (char*) "Asia/Novosibirsk" , 0x04FE9B }, - { (char*) "Asia/Omsk" , 0x050372 }, - { (char*) "Asia/Oral" , 0x050834 }, - { (char*) "Asia/Phnom_Penh" , 0x050C2E }, - { (char*) "Asia/Pontianak" , 0x050D53 }, - { (char*) "Asia/Pyongyang" , 0x050ED6 }, - { (char*) "Asia/Qatar" , 0x050FCF }, - { (char*) "Asia/Qostanay" , 0x051094 }, - { (char*) "Asia/Qyzylorda" , 0x0514BB }, - { (char*) "Asia/Rangoon" , 0x0518D7 }, - { (char*) "Asia/Riyadh" , 0x0519E1 }, - { (char*) "Asia/Saigon" , 0x051A84 }, - { (char*) "Asia/Sakhalin" , 0x051BE1 }, - { (char*) "Asia/Samarkand" , 0x0520A9 }, - { (char*) "Asia/Seoul" , 0x0522F9 }, - { (char*) "Asia/Shanghai" , 0x05256E }, - { (char*) "Asia/Singapore" , 0x0527B7 }, - { (char*) "Asia/Srednekolymsk" , 0x052954 }, - { (char*) "Asia/Taipei" , 0x052E28 }, - { (char*) "Asia/Tashkent" , 0x05312D }, - { (char*) "Asia/Tbilisi" , 0x05338B }, - { (char*) "Asia/Tehran" , 0x053794 }, - { (char*) "Asia/Tel_Aviv" , 0x053C80 }, - { (char*) "Asia/Thimbu" , 0x0545E0 }, - { (char*) "Asia/Thimphu" , 0x0546A9 }, - { (char*) "Asia/Tokyo" , 0x054772 }, - { (char*) "Asia/Tomsk" , 0x0548B3 }, - { (char*) "Asia/Ujung_Pandang" , 0x054D84 }, - { (char*) "Asia/Ulaanbaatar" , 0x054E8E }, - { (char*) "Asia/Ulan_Bator" , 0x055217 }, - { (char*) "Asia/Urumqi" , 0x055590 }, - { (char*) "Asia/Ust-Nera" , 0x055640 }, - { (char*) "Asia/Vientiane" , 0x055B36 }, - { (char*) "Asia/Vladivostok" , 0x055C77 }, - { (char*) "Asia/Yakutsk" , 0x056140 }, - { (char*) "Asia/Yangon" , 0x056608 }, - { (char*) "Asia/Yekaterinburg" , 0x056712 }, - { (char*) "Asia/Yerevan" , 0x056BF9 }, - { (char*) "Atlantic/Azores" , 0x057076 }, - { (char*) "Atlantic/Bermuda" , 0x057DFA }, - { (char*) "Atlantic/Canary" , 0x058762 }, - { (char*) "Atlantic/Cape_Verde" , 0x058EE5 }, - { (char*) "Atlantic/Faeroe" , 0x058FF1 }, - { (char*) "Atlantic/Faroe" , 0x059714 }, - { (char*) "Atlantic/Jan_Mayen" , 0x059E37 }, - { (char*) "Atlantic/Madeira" , 0x05A73D }, - { (char*) "Atlantic/Reykjavik" , 0x05B489 }, - { (char*) "Atlantic/South_Georgia" , 0x05B91F }, - { (char*) "Atlantic/St_Helena" , 0x05B9C1 }, - { (char*) "Atlantic/Stanley" , 0x05BA83 }, - { (char*) "Australia/ACT" , 0x05BF3F }, - { (char*) "Australia/Adelaide" , 0x05C7D9 }, - { (char*) "Australia/Brisbane" , 0x05D094 }, - { (char*) "Australia/Broken_Hill" , 0x05D25A }, - { (char*) "Australia/Canberra" , 0x05DB37 }, - { (char*) "Australia/Currie" , 0x05E3D1 }, - { (char*) "Australia/Darwin" , 0x05ED13 }, - { (char*) "Australia/Eucla" , 0x05EE76 }, - { (char*) "Australia/Hobart" , 0x05F063 }, - { (char*) "Australia/LHI" , 0x05F9AD }, - { (char*) "Australia/Lindeman" , 0x0600EF }, - { (char*) "Australia/Lord_Howe" , 0x0602F5 }, - { (char*) "Australia/Melbourne" , 0x060A47 }, - { (char*) "Australia/North" , 0x0612E9 }, - { (char*) "Australia/NSW" , 0x06143A }, - { (char*) "Australia/Perth" , 0x061CD4 }, - { (char*) "Australia/Queensland" , 0x061EBC }, - { (char*) "Australia/South" , 0x06206B }, - { (char*) "Australia/Sydney" , 0x062917 }, - { (char*) "Australia/Tasmania" , 0x0631CD }, - { (char*) "Australia/Victoria" , 0x063B0F }, - { (char*) "Australia/West" , 0x0643A9 }, - { (char*) "Australia/Yancowinna" , 0x064573 }, - { (char*) "Brazil/Acre" , 0x064E34 }, - { (char*) "Brazil/DeNoronha" , 0x0650A6 }, - { (char*) "Brazil/East" , 0x065370 }, - { (char*) "Brazil/West" , 0x065912 }, - { (char*) "Canada/Atlantic" , 0x065B6C }, - { (char*) "Canada/Central" , 0x0668D8 }, - { (char*) "Canada/Eastern" , 0x067418 }, - { (char*) "Canada/Mountain" , 0x0681CA }, - { (char*) "Canada/Newfoundland" , 0x068AF2 }, - { (char*) "Canada/Pacific" , 0x069945 }, - { (char*) "Canada/Saskatchewan" , 0x06A49D }, - { (char*) "Canada/Yukon" , 0x06A87D }, - { (char*) "CET" , 0x06AED7 }, - { (char*) "Chile/Continental" , 0x06BA58 }, - { (char*) "Chile/EasterIsland" , 0x06C437 }, - { (char*) "CST6CDT" , 0x06CCEE }, - { (char*) "Cuba" , 0x06DB02 }, - { (char*) "EET" , 0x06E47E }, - { (char*) "Egypt" , 0x06ED60 }, - { (char*) "Eire" , 0x06F6CB }, - { (char*) "EST" , 0x07047B }, - { (char*) "EST5EDT" , 0x07053D }, - { (char*) "Etc/GMT" , 0x071329 }, - { (char*) "Etc/GMT+0" , 0x0713A7 }, - { (char*) "Etc/GMT+1" , 0x071425 }, - { (char*) "Etc/GMT+10" , 0x0714A5 }, - { (char*) "Etc/GMT+11" , 0x071526 }, - { (char*) "Etc/GMT+12" , 0x0715A7 }, - { (char*) "Etc/GMT+2" , 0x071628 }, - { (char*) "Etc/GMT+3" , 0x0716A8 }, - { (char*) "Etc/GMT+4" , 0x071728 }, - { (char*) "Etc/GMT+5" , 0x0717A8 }, - { (char*) "Etc/GMT+6" , 0x071828 }, - { (char*) "Etc/GMT+7" , 0x0718A8 }, - { (char*) "Etc/GMT+8" , 0x071928 }, - { (char*) "Etc/GMT+9" , 0x0719A8 }, - { (char*) "Etc/GMT-0" , 0x071A28 }, - { (char*) "Etc/GMT-1" , 0x071AA6 }, - { (char*) "Etc/GMT-10" , 0x071B27 }, - { (char*) "Etc/GMT-11" , 0x071BA9 }, - { (char*) "Etc/GMT-12" , 0x071C2B }, - { (char*) "Etc/GMT-13" , 0x071CAD }, - { (char*) "Etc/GMT-14" , 0x071D2F }, - { (char*) "Etc/GMT-2" , 0x071DB1 }, - { (char*) "Etc/GMT-3" , 0x071E32 }, - { (char*) "Etc/GMT-4" , 0x071EB3 }, - { (char*) "Etc/GMT-5" , 0x071F34 }, - { (char*) "Etc/GMT-6" , 0x071FB5 }, - { (char*) "Etc/GMT-7" , 0x072036 }, - { (char*) "Etc/GMT-8" , 0x0720B7 }, - { (char*) "Etc/GMT-9" , 0x072138 }, - { (char*) "Etc/GMT0" , 0x0721B9 }, - { (char*) "Etc/Greenwich" , 0x072237 }, - { (char*) "Etc/UCT" , 0x0722B5 }, - { (char*) "Etc/Universal" , 0x072333 }, - { (char*) "Etc/UTC" , 0x0723B1 }, - { (char*) "Etc/Zulu" , 0x07242F }, - { (char*) "Europe/Amsterdam" , 0x0724AD }, - { (char*) "Europe/Andorra" , 0x073017 }, - { (char*) "Europe/Astrakhan" , 0x0736F1 }, - { (char*) "Europe/Athens" , 0x073B8E }, - { (char*) "Europe/Belfast" , 0x074470 }, - { (char*) "Europe/Belgrade" , 0x0752CC }, - { (char*) "Europe/Berlin" , 0x075A58 }, - { (char*) "Europe/Bratislava" , 0x07636D }, - { (char*) "Europe/Brussels" , 0x076C76 }, - { (char*) "Europe/Bucharest" , 0x0777F7 }, - { (char*) "Europe/Budapest" , 0x07808B }, - { (char*) "Europe/Busingen" , 0x0789D7 }, - { (char*) "Europe/Chisinau" , 0x079160 }, - { (char*) "Europe/Copenhagen" , 0x079AC2 }, - { (char*) "Europe/Dublin" , 0x07A327 }, - { (char*) "Europe/Gibraltar" , 0x07B0D7 }, - { (char*) "Europe/Guernsey" , 0x07BCDF }, - { (char*) "Europe/Helsinki" , 0x07CB7F }, - { (char*) "Europe/Isle_of_Man" , 0x07D2F7 }, - { (char*) "Europe/Istanbul" , 0x07E143 }, - { (char*) "Europe/Jersey" , 0x07E8DC }, - { (char*) "Europe/Kaliningrad" , 0x07F77C }, - { (char*) "Europe/Kiev" , 0x07FD71 }, - { (char*) "Europe/Kirov" , 0x0805C5 }, - { (char*) "Europe/Kyiv" , 0x080A80 }, - { (char*) "Europe/Lisbon" , 0x0812E3 }, - { (char*) "Europe/Ljubljana" , 0x0820C9 }, - { (char*) "Europe/London" , 0x082855 }, - { (char*) "Europe/Luxembourg" , 0x0836B1 }, - { (char*) "Europe/Madrid" , 0x08423F }, - { (char*) "Europe/Malta" , 0x084C91 }, - { (char*) "Europe/Mariehamn" , 0x0856D9 }, - { (char*) "Europe/Minsk" , 0x085E51 }, - { (char*) "Europe/Monaco" , 0x086378 }, - { (char*) "Europe/Moscow" , 0x086F04 }, - { (char*) "Europe/Nicosia" , 0x087523 }, - { (char*) "Europe/Oslo" , 0x087D01 }, - { (char*) "Europe/Paris" , 0x0885C1 }, - { (char*) "Europe/Podgorica" , 0x08915F }, - { (char*) "Europe/Prague" , 0x0898EB }, - { (char*) "Europe/Riga" , 0x08A1F4 }, - { (char*) "Europe/Rome" , 0x08AA96 }, - { (char*) "Europe/Samara" , 0x08B4F3 }, - { (char*) "Europe/San_Marino" , 0x08B9C9 }, - { (char*) "Europe/Sarajevo" , 0x08C426 }, - { (char*) "Europe/Saratov" , 0x08CBB2 }, - { (char*) "Europe/Simferopol" , 0x08D05F }, - { (char*) "Europe/Skopje" , 0x08D62E }, - { (char*) "Europe/Sofia" , 0x08DDBA }, - { (char*) "Europe/Stockholm" , 0x08E5E3 }, - { (char*) "Europe/Tallinn" , 0x08ED64 }, - { (char*) "Europe/Tirane" , 0x08F5D4 }, - { (char*) "Europe/Tiraspol" , 0x08FE04 }, - { (char*) "Europe/Ulyanovsk" , 0x090766 }, - { (char*) "Europe/Uzhgorod" , 0x090C69 }, - { (char*) "Europe/Vaduz" , 0x0914BD }, - { (char*) "Europe/Vatican" , 0x091C29 }, - { (char*) "Europe/Vienna" , 0x092686 }, - { (char*) "Europe/Vilnius" , 0x092F2A }, - { (char*) "Europe/Volgograd" , 0x0937A8 }, - { (char*) "Europe/Warsaw" , 0x093C6F }, - { (char*) "Europe/Zagreb" , 0x0946D9 }, - { (char*) "Europe/Zaporozhye" , 0x094E65 }, - { (char*) "Europe/Zurich" , 0x0956B9 }, - { (char*) "Factory" , 0x095E3A }, - { (char*) "GB" , 0x095EBA }, - { (char*) "GB-Eire" , 0x096D16 }, - { (char*) "GMT" , 0x097B72 }, - { (char*) "GMT+0" , 0x097BF0 }, - { (char*) "GMT-0" , 0x097C6E }, - { (char*) "GMT0" , 0x097CEC }, - { (char*) "Greenwich" , 0x097D6A }, - { (char*) "Hongkong" , 0x097DE8 }, - { (char*) "HST" , 0x0982C5 }, - { (char*) "Iceland" , 0x09841A }, - { (char*) "Indian/Antananarivo" , 0x0984BA }, - { (char*) "Indian/Chagos" , 0x0985A1 }, - { (char*) "Indian/Christmas" , 0x098666 }, - { (char*) "Indian/Cocos" , 0x098709 }, - { (char*) "Indian/Comoro" , 0x0987B5 }, - { (char*) "Indian/Kerguelen" , 0x098856 }, - { (char*) "Indian/Mahe" , 0x0988F9 }, - { (char*) "Indian/Maldives" , 0x09899C }, - { (char*) "Indian/Mauritius" , 0x098A61 }, - { (char*) "Indian/Mayotte" , 0x098B50 }, - { (char*) "Indian/Reunion" , 0x098BF1 }, - { (char*) "Iran" , 0x098C94 }, - { (char*) "Israel" , 0x099180 }, - { (char*) "Jamaica" , 0x099AE0 }, - { (char*) "Japan" , 0x099CCE }, - { (char*) "Kwajalein" , 0x099E0F }, - { (char*) "Libya" , 0x099F49 }, - { (char*) "MET" , 0x09A1C6 }, - { (char*) "Mexico/BajaNorte" , 0x09AD47 }, - { (char*) "Mexico/BajaSur" , 0x09B6ED }, - { (char*) "Mexico/General" , 0x09BB1D }, - { (char*) "MST" , 0x09BFEF }, - { (char*) "MST7MDT" , 0x09C163 }, - { (char*) "Navajo" , 0x09CB0B }, - { (char*) "NZ" , 0x09D4B3 }, - { (char*) "NZ-CHAT" , 0x09DE44 }, - { (char*) "Pacific/Apia" , 0x09E656 }, - { (char*) "Pacific/Auckland" , 0x09E8B8 }, - { (char*) "Pacific/Bougainville" , 0x09F25C }, - { (char*) "Pacific/Chatham" , 0x09F372 }, - { (char*) "Pacific/Chuuk" , 0x09FB93 }, - { (char*) "Pacific/Easter" , 0x09FCAD }, - { (char*) "Pacific/Efate" , 0x0A0571 }, - { (char*) "Pacific/Enderbury" , 0x0A0789 }, - { (char*) "Pacific/Fakaofo" , 0x0A0871 }, - { (char*) "Pacific/Fiji" , 0x0A0937 }, - { (char*) "Pacific/Funafuti" , 0x0A0B77 }, - { (char*) "Pacific/Galapagos" , 0x0A0C1B }, - { (char*) "Pacific/Gambier" , 0x0A0D18 }, - { (char*) "Pacific/Guadalcanal" , 0x0A0DC9 }, - { (char*) "Pacific/Guam" , 0x0A0E6D }, - { (char*) "Pacific/Honolulu" , 0x0A1067 }, - { (char*) "Pacific/Johnston" , 0x0A11C2 }, - { (char*) "Pacific/Kanton" , 0x0A1317 }, - { (char*) "Pacific/Kiritimati" , 0x0A140E }, - { (char*) "Pacific/Kosrae" , 0x0A1506 }, - { (char*) "Pacific/Kwajalein" , 0x0A1669 }, - { (char*) "Pacific/Majuro" , 0x0A17AC }, - { (char*) "Pacific/Marquesas" , 0x0A18F8 }, - { (char*) "Pacific/Midway" , 0x0A19B4 }, - { (char*) "Pacific/Nauru" , 0x0A1AA7 }, - { (char*) "Pacific/Niue" , 0x0A1BA1 }, - { (char*) "Pacific/Norfolk" , 0x0A1C6A }, - { (char*) "Pacific/Noumea" , 0x0A1FD8 }, - { (char*) "Pacific/Pago_Pago" , 0x0A2106 }, - { (char*) "Pacific/Palau" , 0x0A21C1 }, - { (char*) "Pacific/Pitcairn" , 0x0A2273 }, - { (char*) "Pacific/Pohnpei" , 0x0A233B }, - { (char*) "Pacific/Ponape" , 0x0A2476 }, - { (char*) "Pacific/Port_Moresby" , 0x0A251A }, - { (char*) "Pacific/Rarotonga" , 0x0A25EA }, - { (char*) "Pacific/Saipan" , 0x0A2843 }, - { (char*) "Pacific/Samoa" , 0x0A2A2F }, - { (char*) "Pacific/Tahiti" , 0x0A2AEA }, - { (char*) "Pacific/Tarawa" , 0x0A2B9C }, - { (char*) "Pacific/Tongatapu" , 0x0A2C4F }, - { (char*) "Pacific/Truk" , 0x0A2DC1 }, - { (char*) "Pacific/Wake" , 0x0A2E79 }, - { (char*) "Pacific/Wallis" , 0x0A2F28 }, - { (char*) "Pacific/Yap" , 0x0A2FCC }, - { (char*) "Poland" , 0x0A3084 }, - { (char*) "Portugal" , 0x0A3AEE }, - { (char*) "PRC" , 0x0A48C1 }, - { (char*) "PST8PDT" , 0x0A4AFE }, - { (char*) "ROC" , 0x0A562E }, - { (char*) "ROK" , 0x0A5933 }, - { (char*) "Singapore" , 0x0A5BA8 }, - { (char*) "Turkey" , 0x0A5D45 }, - { (char*) "UCT" , 0x0A64DE }, - { (char*) "Universal" , 0x0A655C }, - { (char*) "US/Alaska" , 0x0A65DA }, - { (char*) "US/Aleutian" , 0x0A6F29 }, - { (char*) "US/Arizona" , 0x0A7869 }, - { (char*) "US/Central" , 0x0A79DD }, - { (char*) "US/East-Indiana" , 0x0A87F1 }, - { (char*) "US/Eastern" , 0x0A8E8F }, - { (char*) "US/Hawaii" , 0x0A9C7B }, - { (char*) "US/Indiana-Starke" , 0x0A9DD0 }, - { (char*) "US/Michigan" , 0x0AA768 }, - { (char*) "US/Mountain" , 0x0AB02A }, - { (char*) "US/Pacific" , 0x0AB9D2 }, - { (char*) "US/Samoa" , 0x0AC502 }, - { (char*) "UTC" , 0x0AC5BD }, - { (char*) "W-SU" , 0x0AC63B }, - { (char*) "WET" , 0x0ACC46 }, - { (char*) "Zulu" , 0x0ADA19 }, + { (char*) "America/Coyhaique" , 0x011AEB }, + { (char*) "America/Creston" , 0x012351 }, + { (char*) "America/Cuiaba" , 0x01243F }, + { (char*) "America/Curacao" , 0x0129D0 }, + { (char*) "America/Danmarkshavn" , 0x012A96 }, + { (char*) "America/Dawson" , 0x012D76 }, + { (char*) "America/Dawson_Creek" , 0x0133E2 }, + { (char*) "America/Denver" , 0x013828 }, + { (char*) "America/Detroit" , 0x0141E5 }, + { (char*) "America/Dominica" , 0x014AC0 }, + { (char*) "America/Edmonton" , 0x014B60 }, + { (char*) "America/Eirunepe" , 0x0154AA }, + { (char*) "America/El_Salvador" , 0x015747 }, + { (char*) "America/Ensenada" , 0x015833 }, + { (char*) "America/Fort_Nelson" , 0x0161D9 }, + { (char*) "America/Fort_Wayne" , 0x016AB9 }, + { (char*) "America/Fortaleza" , 0x017157 }, + { (char*) "America/Glace_Bay" , 0x017447 }, + { (char*) "America/Godthab" , 0x017CFE }, + { (char*) "America/Goose_Bay" , 0x01846B }, + { (char*) "America/Grand_Turk" , 0x019121 }, + { (char*) "America/Grenada" , 0x019857 }, + { (char*) "America/Guadeloupe" , 0x0198F7 }, + { (char*) "America/Guatemala" , 0x019997 }, + { (char*) "America/Guayaquil" , 0x019ABB }, + { (char*) "America/Guyana" , 0x019BC1 }, + { (char*) "America/Halifax" , 0x019CC5 }, + { (char*) "America/Havana" , 0x01AA4F }, + { (char*) "America/Hermosillo" , 0x01B3CB }, + { (char*) "America/Indiana/Indianapolis" , 0x01B561 }, + { (char*) "America/Indiana/Knox" , 0x01BC18 }, + { (char*) "America/Indiana/Marengo" , 0x01C5C5 }, + { (char*) "America/Indiana/Petersburg" , 0x01CCB2 }, + { (char*) "America/Indiana/Tell_City" , 0x01D451 }, + { (char*) "America/Indiana/Vevay" , 0x01DB15 }, + { (char*) "America/Indiana/Vincennes" , 0x01E0D1 }, + { (char*) "America/Indiana/Winamac" , 0x01E7A7 }, + { (char*) "America/Indianapolis" , 0x01EECB }, + { (char*) "America/Inuvik" , 0x01F569 }, + { (char*) "America/Iqaluit" , 0x01FDA3 }, + { (char*) "America/Jamaica" , 0x020662 }, + { (char*) "America/Jujuy" , 0x020850 }, + { (char*) "America/Juneau" , 0x020C66 }, + { (char*) "America/Kentucky/Louisville" , 0x0215B7 }, + { (char*) "America/Kentucky/Monticello" , 0x0220C5 }, + { (char*) "America/Knox_IN" , 0x022A25 }, + { (char*) "America/Kralendijk" , 0x0233BD }, + { (char*) "America/La_Paz" , 0x0234BF }, + { (char*) "America/Lima" , 0x0235A5 }, + { (char*) "America/Los_Angeles" , 0x023739 }, + { (char*) "America/Louisville" , 0x024270 }, + { (char*) "America/Lower_Princes" , 0x024D60 }, + { (char*) "America/Maceio" , 0x024E62 }, + { (char*) "America/Managua" , 0x025158 }, + { (char*) "America/Manaus" , 0x025312 }, + { (char*) "America/Marigot" , 0x02557B }, + { (char*) "America/Martinique" , 0x02567D }, + { (char*) "America/Matamoros" , 0x025771 }, + { (char*) "America/Mazatlan" , 0x025D33 }, + { (char*) "America/Mendoza" , 0x026195 }, + { (char*) "America/Menominee" , 0x0265C7 }, + { (char*) "America/Merida" , 0x026ED4 }, + { (char*) "America/Metlakatla" , 0x0272DD }, + { (char*) "America/Mexico_City" , 0x02788F }, + { (char*) "America/Miquelon" , 0x027D6F }, + { (char*) "America/Moncton" , 0x0283EF }, + { (char*) "America/Monterrey" , 0x029065 }, + { (char*) "America/Montevideo" , 0x029501 }, + { (char*) "America/Montreal" , 0x029AE5 }, + { (char*) "America/Montserrat" , 0x02A897 }, + { (char*) "America/Nassau" , 0x02A937 }, + { (char*) "America/New_York" , 0x02B297 }, + { (char*) "America/Nipigon" , 0x02C097 }, + { (char*) "America/Nome" , 0x02CE49 }, + { (char*) "America/Noronha" , 0x02D7A1 }, + { (char*) "America/North_Dakota/Beulah" , 0x02DA7B }, + { (char*) "America/North_Dakota/Center" , 0x02E3F8 }, + { (char*) "America/North_Dakota/New_Salem" , 0x02ED75 }, + { (char*) "America/Nuuk" , 0x02F6F8 }, + { (char*) "America/Ojinaga" , 0x02FE76 }, + { (char*) "America/Panama" , 0x030492 }, + { (char*) "America/Pangnirtung" , 0x030554 }, + { (char*) "America/Paramaribo" , 0x030DFA }, + { (char*) "America/Phoenix" , 0x030EFE }, + { (char*) "America/Port-au-Prince" , 0x03108A }, + { (char*) "America/Port_of_Spain" , 0x031630 }, + { (char*) "America/Porto_Acre" , 0x0316D0 }, + { (char*) "America/Porto_Velho" , 0x031942 }, + { (char*) "America/Puerto_Rico" , 0x031B88 }, + { (char*) "America/Punta_Arenas" , 0x031C8A }, + { (char*) "America/Rainy_River" , 0x032415 }, + { (char*) "America/Rankin_Inlet" , 0x032F55 }, + { (char*) "America/Recife" , 0x033789 }, + { (char*) "America/Regina" , 0x033A5D }, + { (char*) "America/Resolute" , 0x033E52 }, + { (char*) "America/Rio_Branco" , 0x034687 }, + { (char*) "America/Rosario" , 0x0348FD }, + { (char*) "America/Santa_Isabel" , 0x034D2F }, + { (char*) "America/Santarem" , 0x0356D5 }, + { (char*) "America/Santiago" , 0x035938 }, + { (char*) "America/Santo_Domingo" , 0x036324 }, + { (char*) "America/Sao_Paulo" , 0x0364FA }, + { (char*) "America/Scoresbysund" , 0x036AD2 }, + { (char*) "America/Shiprock" , 0x03728A }, + { (char*) "America/Sitka" , 0x037C32 }, + { (char*) "America/St_Barthelemy" , 0x03856A }, + { (char*) "America/St_Johns" , 0x03866C }, + { (char*) "America/St_Kitts" , 0x0394DA }, + { (char*) "America/St_Lucia" , 0x03957A }, + { (char*) "America/St_Thomas" , 0x03963C }, + { (char*) "America/St_Vincent" , 0x0396DC }, + { (char*) "America/Swift_Current" , 0x03979E }, + { (char*) "America/Tegucigalpa" , 0x0399EC }, + { (char*) "America/Thule" , 0x039AF4 }, + { (char*) "America/Thunder_Bay" , 0x03A0EC }, + { (char*) "America/Tijuana" , 0x03AE9E }, + { (char*) "America/Toronto" , 0x03B853 }, + { (char*) "America/Tortola" , 0x03C623 }, + { (char*) "America/Vancouver" , 0x03C6C3 }, + { (char*) "America/Virgin" , 0x03D234 }, + { (char*) "America/Whitehorse" , 0x03D336 }, + { (char*) "America/Winnipeg" , 0x03D9A2 }, + { (char*) "America/Yakutat" , 0x03E4FF }, + { (char*) "America/Yellowknife" , 0x03EE1C }, + { (char*) "Antarctica/Casey" , 0x03F744 }, + { (char*) "Antarctica/Davis" , 0x03F8FC }, + { (char*) "Antarctica/DumontDUrville" , 0x03FA28 }, + { (char*) "Antarctica/Macquarie" , 0x03FAF8 }, + { (char*) "Antarctica/Mawson" , 0x0403E8 }, + { (char*) "Antarctica/McMurdo" , 0x0404B3 }, + { (char*) "Antarctica/Palmer" , 0x040CAE }, + { (char*) "Antarctica/Rothera" , 0x04123C }, + { (char*) "Antarctica/South_Pole" , 0x0412E5 }, + { (char*) "Antarctica/Syowa" , 0x041C76 }, + { (char*) "Antarctica/Troll" , 0x041D1E }, + { (char*) "Antarctica/Vostok" , 0x0421AB }, + { (char*) "Arctic/Longyearbyen" , 0x042292 }, + { (char*) "Asia/Aden" , 0x042B98 }, + { (char*) "Asia/Almaty" , 0x042C3B }, + { (char*) "Asia/Amman" , 0x043030 }, + { (char*) "Asia/Anadyr" , 0x0435D5 }, + { (char*) "Asia/Aqtau" , 0x043A8A }, + { (char*) "Asia/Aqtobe" , 0x043E74 }, + { (char*) "Asia/Ashgabat" , 0x044272 }, + { (char*) "Asia/Ashkhabad" , 0x0444DB }, + { (char*) "Asia/Atyrau" , 0x044744 }, + { (char*) "Asia/Baghdad" , 0x044B36 }, + { (char*) "Asia/Bahrain" , 0x044F0B }, + { (char*) "Asia/Baku" , 0x044FF6 }, + { (char*) "Asia/Bangkok" , 0x0454BF }, + { (char*) "Asia/Barnaul" , 0x045584 }, + { (char*) "Asia/Beirut" , 0x045A55 }, + { (char*) "Asia/Bishkek" , 0x0462CB }, + { (char*) "Asia/Brunei" , 0x0466A0 }, + { (char*) "Asia/Calcutta" , 0x046769 }, + { (char*) "Asia/Chita" , 0x046892 }, + { (char*) "Asia/Choibalsan" , 0x046D69 }, + { (char*) "Asia/Chongqing" , 0x0470E2 }, + { (char*) "Asia/Chungking" , 0x04731F }, + { (char*) "Asia/Colombo" , 0x04755C }, + { (char*) "Asia/Dacca" , 0x0476CE }, + { (char*) "Asia/Damascus" , 0x04781D }, + { (char*) "Asia/Dhaka" , 0x047F7A }, + { (char*) "Asia/Dili" , 0x0480C9 }, + { (char*) "Asia/Dubai" , 0x0481D6 }, + { (char*) "Asia/Dushanbe" , 0x048279 }, + { (char*) "Asia/Famagusta" , 0x0484C6 }, + { (char*) "Asia/Gaza" , 0x048CCD }, + { (char*) "Asia/Harbin" , 0x049BE7 }, + { (char*) "Asia/Hebron" , 0x049E24 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x04AD59 }, + { (char*) "Asia/Hong_Kong" , 0x04AEB6 }, + { (char*) "Asia/Hovd" , 0x04B393 }, + { (char*) "Asia/Irkutsk" , 0x04B722 }, + { (char*) "Asia/Istanbul" , 0x04BC15 }, + { (char*) "Asia/Jakarta" , 0x04C3AE }, + { (char*) "Asia/Jayapura" , 0x04C546 }, + { (char*) "Asia/Jerusalem" , 0x04C665 }, + { (char*) "Asia/Kabul" , 0x04CFC5 }, + { (char*) "Asia/Kamchatka" , 0x04D093 }, + { (char*) "Asia/Karachi" , 0x04D531 }, + { (char*) "Asia/Kashgar" , 0x04D6B8 }, + { (char*) "Asia/Kathmandu" , 0x04D75B }, + { (char*) "Asia/Katmandu" , 0x04D82D }, + { (char*) "Asia/Khandyga" , 0x04D8FF }, + { (char*) "Asia/Kolkata" , 0x04DE12 }, + { (char*) "Asia/Krasnoyarsk" , 0x04DF3B }, + { (char*) "Asia/Kuala_Lumpur" , 0x04E409 }, + { (char*) "Asia/Kuching" , 0x04E5BA }, + { (char*) "Asia/Kuwait" , 0x04E7A9 }, + { (char*) "Asia/Macao" , 0x04E84C }, + { (char*) "Asia/Macau" , 0x04ED23 }, + { (char*) "Asia/Magadan" , 0x04F1FA }, + { (char*) "Asia/Makassar" , 0x04F6CE }, + { (char*) "Asia/Manila" , 0x04F821 }, + { (char*) "Asia/Muscat" , 0x04F9D3 }, + { (char*) "Asia/Nicosia" , 0x04FA76 }, + { (char*) "Asia/Novokuznetsk" , 0x050262 }, + { (char*) "Asia/Novosibirsk" , 0x0506FE }, + { (char*) "Asia/Omsk" , 0x050BD5 }, + { (char*) "Asia/Oral" , 0x051097 }, + { (char*) "Asia/Phnom_Penh" , 0x051491 }, + { (char*) "Asia/Pontianak" , 0x0515B6 }, + { (char*) "Asia/Pyongyang" , 0x051739 }, + { (char*) "Asia/Qatar" , 0x051832 }, + { (char*) "Asia/Qostanay" , 0x0518F7 }, + { (char*) "Asia/Qyzylorda" , 0x051D1E }, + { (char*) "Asia/Rangoon" , 0x05213A }, + { (char*) "Asia/Riyadh" , 0x052244 }, + { (char*) "Asia/Saigon" , 0x0522E7 }, + { (char*) "Asia/Sakhalin" , 0x052444 }, + { (char*) "Asia/Samarkand" , 0x05290C }, + { (char*) "Asia/Seoul" , 0x052B5C }, + { (char*) "Asia/Shanghai" , 0x052DD1 }, + { (char*) "Asia/Singapore" , 0x05301A }, + { (char*) "Asia/Srednekolymsk" , 0x0531B7 }, + { (char*) "Asia/Taipei" , 0x05368B }, + { (char*) "Asia/Tashkent" , 0x053990 }, + { (char*) "Asia/Tbilisi" , 0x053BEE }, + { (char*) "Asia/Tehran" , 0x053FF7 }, + { (char*) "Asia/Tel_Aviv" , 0x0544E3 }, + { (char*) "Asia/Thimbu" , 0x054E43 }, + { (char*) "Asia/Thimphu" , 0x054F0C }, + { (char*) "Asia/Tokyo" , 0x054FD5 }, + { (char*) "Asia/Tomsk" , 0x055116 }, + { (char*) "Asia/Ujung_Pandang" , 0x0555E7 }, + { (char*) "Asia/Ulaanbaatar" , 0x0556F1 }, + { (char*) "Asia/Ulan_Bator" , 0x055A7A }, + { (char*) "Asia/Urumqi" , 0x055DF3 }, + { (char*) "Asia/Ust-Nera" , 0x055EA3 }, + { (char*) "Asia/Vientiane" , 0x056399 }, + { (char*) "Asia/Vladivostok" , 0x0564DA }, + { (char*) "Asia/Yakutsk" , 0x0569A3 }, + { (char*) "Asia/Yangon" , 0x056E6B }, + { (char*) "Asia/Yekaterinburg" , 0x056F75 }, + { (char*) "Asia/Yerevan" , 0x05745C }, + { (char*) "Atlantic/Azores" , 0x0578D9 }, + { (char*) "Atlantic/Bermuda" , 0x05865D }, + { (char*) "Atlantic/Canary" , 0x058FC5 }, + { (char*) "Atlantic/Cape_Verde" , 0x059748 }, + { (char*) "Atlantic/Faeroe" , 0x059854 }, + { (char*) "Atlantic/Faroe" , 0x059F77 }, + { (char*) "Atlantic/Jan_Mayen" , 0x05A69A }, + { (char*) "Atlantic/Madeira" , 0x05AFA0 }, + { (char*) "Atlantic/Reykjavik" , 0x05BCEC }, + { (char*) "Atlantic/South_Georgia" , 0x05C182 }, + { (char*) "Atlantic/St_Helena" , 0x05C224 }, + { (char*) "Atlantic/Stanley" , 0x05C2E6 }, + { (char*) "Australia/ACT" , 0x05C7A2 }, + { (char*) "Australia/Adelaide" , 0x05D03C }, + { (char*) "Australia/Brisbane" , 0x05D8F7 }, + { (char*) "Australia/Broken_Hill" , 0x05DABD }, + { (char*) "Australia/Canberra" , 0x05E39A }, + { (char*) "Australia/Currie" , 0x05EC34 }, + { (char*) "Australia/Darwin" , 0x05F576 }, + { (char*) "Australia/Eucla" , 0x05F6D9 }, + { (char*) "Australia/Hobart" , 0x05F8C6 }, + { (char*) "Australia/LHI" , 0x060210 }, + { (char*) "Australia/Lindeman" , 0x060952 }, + { (char*) "Australia/Lord_Howe" , 0x060B58 }, + { (char*) "Australia/Melbourne" , 0x0612AA }, + { (char*) "Australia/North" , 0x061B4C }, + { (char*) "Australia/NSW" , 0x061C9D }, + { (char*) "Australia/Perth" , 0x062537 }, + { (char*) "Australia/Queensland" , 0x06271F }, + { (char*) "Australia/South" , 0x0628CE }, + { (char*) "Australia/Sydney" , 0x06317A }, + { (char*) "Australia/Tasmania" , 0x063A30 }, + { (char*) "Australia/Victoria" , 0x064372 }, + { (char*) "Australia/West" , 0x064C0C }, + { (char*) "Australia/Yancowinna" , 0x064DD6 }, + { (char*) "Brazil/Acre" , 0x065697 }, + { (char*) "Brazil/DeNoronha" , 0x065909 }, + { (char*) "Brazil/East" , 0x065BD3 }, + { (char*) "Brazil/West" , 0x066175 }, + { (char*) "Canada/Atlantic" , 0x0663CF }, + { (char*) "Canada/Central" , 0x06713B }, + { (char*) "Canada/Eastern" , 0x067C7B }, + { (char*) "Canada/Mountain" , 0x068A2D }, + { (char*) "Canada/Newfoundland" , 0x069355 }, + { (char*) "Canada/Pacific" , 0x06A1A8 }, + { (char*) "Canada/Saskatchewan" , 0x06AD00 }, + { (char*) "Canada/Yukon" , 0x06B0E0 }, + { (char*) "CET" , 0x06B73A }, + { (char*) "Chile/Continental" , 0x06C2BB }, + { (char*) "Chile/EasterIsland" , 0x06CC9A }, + { (char*) "CST6CDT" , 0x06D551 }, + { (char*) "Cuba" , 0x06E365 }, + { (char*) "EET" , 0x06ECE1 }, + { (char*) "Egypt" , 0x06F5C3 }, + { (char*) "Eire" , 0x06FF2E }, + { (char*) "EST" , 0x070CDE }, + { (char*) "EST5EDT" , 0x070DA0 }, + { (char*) "Etc/GMT" , 0x071B8C }, + { (char*) "Etc/GMT+0" , 0x071C0A }, + { (char*) "Etc/GMT+1" , 0x071C88 }, + { (char*) "Etc/GMT+10" , 0x071D08 }, + { (char*) "Etc/GMT+11" , 0x071D89 }, + { (char*) "Etc/GMT+12" , 0x071E0A }, + { (char*) "Etc/GMT+2" , 0x071E8B }, + { (char*) "Etc/GMT+3" , 0x071F0B }, + { (char*) "Etc/GMT+4" , 0x071F8B }, + { (char*) "Etc/GMT+5" , 0x07200B }, + { (char*) "Etc/GMT+6" , 0x07208B }, + { (char*) "Etc/GMT+7" , 0x07210B }, + { (char*) "Etc/GMT+8" , 0x07218B }, + { (char*) "Etc/GMT+9" , 0x07220B }, + { (char*) "Etc/GMT-0" , 0x07228B }, + { (char*) "Etc/GMT-1" , 0x072309 }, + { (char*) "Etc/GMT-10" , 0x07238A }, + { (char*) "Etc/GMT-11" , 0x07240C }, + { (char*) "Etc/GMT-12" , 0x07248E }, + { (char*) "Etc/GMT-13" , 0x072510 }, + { (char*) "Etc/GMT-14" , 0x072592 }, + { (char*) "Etc/GMT-2" , 0x072614 }, + { (char*) "Etc/GMT-3" , 0x072695 }, + { (char*) "Etc/GMT-4" , 0x072716 }, + { (char*) "Etc/GMT-5" , 0x072797 }, + { (char*) "Etc/GMT-6" , 0x072818 }, + { (char*) "Etc/GMT-7" , 0x072899 }, + { (char*) "Etc/GMT-8" , 0x07291A }, + { (char*) "Etc/GMT-9" , 0x07299B }, + { (char*) "Etc/GMT0" , 0x072A1C }, + { (char*) "Etc/Greenwich" , 0x072A9A }, + { (char*) "Etc/UCT" , 0x072B18 }, + { (char*) "Etc/Universal" , 0x072B96 }, + { (char*) "Etc/UTC" , 0x072C14 }, + { (char*) "Etc/Zulu" , 0x072C92 }, + { (char*) "Europe/Amsterdam" , 0x072D10 }, + { (char*) "Europe/Andorra" , 0x07387A }, + { (char*) "Europe/Astrakhan" , 0x073F54 }, + { (char*) "Europe/Athens" , 0x0743F1 }, + { (char*) "Europe/Belfast" , 0x074CD3 }, + { (char*) "Europe/Belgrade" , 0x075B2F }, + { (char*) "Europe/Berlin" , 0x0762BB }, + { (char*) "Europe/Bratislava" , 0x076BD0 }, + { (char*) "Europe/Brussels" , 0x0774D9 }, + { (char*) "Europe/Bucharest" , 0x07805A }, + { (char*) "Europe/Budapest" , 0x0788EE }, + { (char*) "Europe/Busingen" , 0x07923A }, + { (char*) "Europe/Chisinau" , 0x0799C3 }, + { (char*) "Europe/Copenhagen" , 0x07A325 }, + { (char*) "Europe/Dublin" , 0x07AB8A }, + { (char*) "Europe/Gibraltar" , 0x07B93A }, + { (char*) "Europe/Guernsey" , 0x07C542 }, + { (char*) "Europe/Helsinki" , 0x07D3E2 }, + { (char*) "Europe/Isle_of_Man" , 0x07DB5A }, + { (char*) "Europe/Istanbul" , 0x07E9A6 }, + { (char*) "Europe/Jersey" , 0x07F13F }, + { (char*) "Europe/Kaliningrad" , 0x07FFDF }, + { (char*) "Europe/Kiev" , 0x0805D4 }, + { (char*) "Europe/Kirov" , 0x080E28 }, + { (char*) "Europe/Kyiv" , 0x0812E3 }, + { (char*) "Europe/Lisbon" , 0x081B46 }, + { (char*) "Europe/Ljubljana" , 0x08292C }, + { (char*) "Europe/London" , 0x0830B8 }, + { (char*) "Europe/Luxembourg" , 0x083F14 }, + { (char*) "Europe/Madrid" , 0x084AA2 }, + { (char*) "Europe/Malta" , 0x0854F4 }, + { (char*) "Europe/Mariehamn" , 0x085F3C }, + { (char*) "Europe/Minsk" , 0x0866B4 }, + { (char*) "Europe/Monaco" , 0x086BDB }, + { (char*) "Europe/Moscow" , 0x087767 }, + { (char*) "Europe/Nicosia" , 0x087D86 }, + { (char*) "Europe/Oslo" , 0x088564 }, + { (char*) "Europe/Paris" , 0x088E24 }, + { (char*) "Europe/Podgorica" , 0x0899C2 }, + { (char*) "Europe/Prague" , 0x08A14E }, + { (char*) "Europe/Riga" , 0x08AA57 }, + { (char*) "Europe/Rome" , 0x08B2F9 }, + { (char*) "Europe/Samara" , 0x08BD56 }, + { (char*) "Europe/San_Marino" , 0x08C22C }, + { (char*) "Europe/Sarajevo" , 0x08CC89 }, + { (char*) "Europe/Saratov" , 0x08D415 }, + { (char*) "Europe/Simferopol" , 0x08D8C2 }, + { (char*) "Europe/Skopje" , 0x08DE91 }, + { (char*) "Europe/Sofia" , 0x08E61D }, + { (char*) "Europe/Stockholm" , 0x08EE46 }, + { (char*) "Europe/Tallinn" , 0x08F5C7 }, + { (char*) "Europe/Tirane" , 0x08FE37 }, + { (char*) "Europe/Tiraspol" , 0x090667 }, + { (char*) "Europe/Ulyanovsk" , 0x090FC9 }, + { (char*) "Europe/Uzhgorod" , 0x0914CC }, + { (char*) "Europe/Vaduz" , 0x091D20 }, + { (char*) "Europe/Vatican" , 0x09248C }, + { (char*) "Europe/Vienna" , 0x092EE9 }, + { (char*) "Europe/Vilnius" , 0x09378D }, + { (char*) "Europe/Volgograd" , 0x09400B }, + { (char*) "Europe/Warsaw" , 0x0944D2 }, + { (char*) "Europe/Zagreb" , 0x094F3C }, + { (char*) "Europe/Zaporozhye" , 0x0956C8 }, + { (char*) "Europe/Zurich" , 0x095F1C }, + { (char*) "Factory" , 0x09669D }, + { (char*) "GB" , 0x09671D }, + { (char*) "GB-Eire" , 0x097579 }, + { (char*) "GMT" , 0x0983D5 }, + { (char*) "GMT+0" , 0x098453 }, + { (char*) "GMT-0" , 0x0984D1 }, + { (char*) "GMT0" , 0x09854F }, + { (char*) "Greenwich" , 0x0985CD }, + { (char*) "Hongkong" , 0x09864B }, + { (char*) "HST" , 0x098B28 }, + { (char*) "Iceland" , 0x098C7D }, + { (char*) "Indian/Antananarivo" , 0x098D1D }, + { (char*) "Indian/Chagos" , 0x098E04 }, + { (char*) "Indian/Christmas" , 0x098EC9 }, + { (char*) "Indian/Cocos" , 0x098F6C }, + { (char*) "Indian/Comoro" , 0x099018 }, + { (char*) "Indian/Kerguelen" , 0x0990B9 }, + { (char*) "Indian/Mahe" , 0x09915C }, + { (char*) "Indian/Maldives" , 0x0991FF }, + { (char*) "Indian/Mauritius" , 0x0992C4 }, + { (char*) "Indian/Mayotte" , 0x0993B3 }, + { (char*) "Indian/Reunion" , 0x099454 }, + { (char*) "Iran" , 0x0994F7 }, + { (char*) "Israel" , 0x0999E3 }, + { (char*) "Jamaica" , 0x09A343 }, + { (char*) "Japan" , 0x09A531 }, + { (char*) "Kwajalein" , 0x09A672 }, + { (char*) "Libya" , 0x09A7AC }, + { (char*) "MET" , 0x09AA29 }, + { (char*) "Mexico/BajaNorte" , 0x09B5AA }, + { (char*) "Mexico/BajaSur" , 0x09BF50 }, + { (char*) "Mexico/General" , 0x09C380 }, + { (char*) "MST" , 0x09C852 }, + { (char*) "MST7MDT" , 0x09C9C6 }, + { (char*) "Navajo" , 0x09D36E }, + { (char*) "NZ" , 0x09DD16 }, + { (char*) "NZ-CHAT" , 0x09E6A7 }, + { (char*) "Pacific/Apia" , 0x09EEB9 }, + { (char*) "Pacific/Auckland" , 0x09F11B }, + { (char*) "Pacific/Bougainville" , 0x09FABF }, + { (char*) "Pacific/Chatham" , 0x09FBD5 }, + { (char*) "Pacific/Chuuk" , 0x0A03F6 }, + { (char*) "Pacific/Easter" , 0x0A0510 }, + { (char*) "Pacific/Efate" , 0x0A0DD4 }, + { (char*) "Pacific/Enderbury" , 0x0A0FEC }, + { (char*) "Pacific/Fakaofo" , 0x0A10D4 }, + { (char*) "Pacific/Fiji" , 0x0A119A }, + { (char*) "Pacific/Funafuti" , 0x0A13DA }, + { (char*) "Pacific/Galapagos" , 0x0A147E }, + { (char*) "Pacific/Gambier" , 0x0A157B }, + { (char*) "Pacific/Guadalcanal" , 0x0A162C }, + { (char*) "Pacific/Guam" , 0x0A16D0 }, + { (char*) "Pacific/Honolulu" , 0x0A18CA }, + { (char*) "Pacific/Johnston" , 0x0A1A25 }, + { (char*) "Pacific/Kanton" , 0x0A1B7A }, + { (char*) "Pacific/Kiritimati" , 0x0A1C71 }, + { (char*) "Pacific/Kosrae" , 0x0A1D69 }, + { (char*) "Pacific/Kwajalein" , 0x0A1ECC }, + { (char*) "Pacific/Majuro" , 0x0A200F }, + { (char*) "Pacific/Marquesas" , 0x0A215B }, + { (char*) "Pacific/Midway" , 0x0A2217 }, + { (char*) "Pacific/Nauru" , 0x0A230A }, + { (char*) "Pacific/Niue" , 0x0A2404 }, + { (char*) "Pacific/Norfolk" , 0x0A24CD }, + { (char*) "Pacific/Noumea" , 0x0A283B }, + { (char*) "Pacific/Pago_Pago" , 0x0A2969 }, + { (char*) "Pacific/Palau" , 0x0A2A24 }, + { (char*) "Pacific/Pitcairn" , 0x0A2AD6 }, + { (char*) "Pacific/Pohnpei" , 0x0A2B9E }, + { (char*) "Pacific/Ponape" , 0x0A2CD9 }, + { (char*) "Pacific/Port_Moresby" , 0x0A2D7D }, + { (char*) "Pacific/Rarotonga" , 0x0A2E4D }, + { (char*) "Pacific/Saipan" , 0x0A30A6 }, + { (char*) "Pacific/Samoa" , 0x0A3292 }, + { (char*) "Pacific/Tahiti" , 0x0A334D }, + { (char*) "Pacific/Tarawa" , 0x0A33FF }, + { (char*) "Pacific/Tongatapu" , 0x0A34B2 }, + { (char*) "Pacific/Truk" , 0x0A3624 }, + { (char*) "Pacific/Wake" , 0x0A36DC }, + { (char*) "Pacific/Wallis" , 0x0A378B }, + { (char*) "Pacific/Yap" , 0x0A382F }, + { (char*) "Poland" , 0x0A38E7 }, + { (char*) "Portugal" , 0x0A4351 }, + { (char*) "PRC" , 0x0A5124 }, + { (char*) "PST8PDT" , 0x0A5361 }, + { (char*) "ROC" , 0x0A5E91 }, + { (char*) "ROK" , 0x0A6196 }, + { (char*) "Singapore" , 0x0A640B }, + { (char*) "Turkey" , 0x0A65A8 }, + { (char*) "UCT" , 0x0A6D41 }, + { (char*) "Universal" , 0x0A6DBF }, + { (char*) "US/Alaska" , 0x0A6E3D }, + { (char*) "US/Aleutian" , 0x0A778C }, + { (char*) "US/Arizona" , 0x0A80CC }, + { (char*) "US/Central" , 0x0A8240 }, + { (char*) "US/East-Indiana" , 0x0A9054 }, + { (char*) "US/Eastern" , 0x0A96F2 }, + { (char*) "US/Hawaii" , 0x0AA4DE }, + { (char*) "US/Indiana-Starke" , 0x0AA633 }, + { (char*) "US/Michigan" , 0x0AAFCB }, + { (char*) "US/Mountain" , 0x0AB88D }, + { (char*) "US/Pacific" , 0x0AC235 }, + { (char*) "US/Samoa" , 0x0ACD65 }, + { (char*) "UTC" , 0x0ACE20 }, + { (char*) "W-SU" , 0x0ACE9E }, + { (char*) "WET" , 0x0AD4A9 }, + { (char*) "Zulu" , 0x0AE27C }, }; -const unsigned char timelib_timezone_db_data_builtin[711319] = { +const unsigned char timelib_timezone_db_data_builtin[713466] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -29630,6 +29720,143 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x54, 0x00, 0x43, 0x53, 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, +0x8F, 0x30, 0x47, 0x45, 0x9B, 0x5C, 0xE5, 0x50, 0x9F, 0x7C, 0xE2, 0xC5, 0xA1, 0x00, 0x71, 0xC0, +0xB0, 0x5E, 0x77, 0xC5, 0xB1, 0x77, 0x3D, 0x40, 0xB2, 0x41, 0x00, 0xD0, 0xB3, 0x58, 0x70, 0xC0, +0xB4, 0x22, 0x34, 0x50, 0xB5, 0x39, 0xA4, 0x40, 0xB6, 0x03, 0x67, 0xD0, 0xB7, 0x1A, 0xD7, 0xC0, +0xB7, 0xE4, 0x9B, 0x50, 0xB8, 0xFD, 0x5C, 0xC0, 0xB9, 0xC7, 0x20, 0x50, 0xCC, 0x1C, 0x6E, 0x40, +0xCC, 0x6C, 0xE7, 0xD0, 0xD4, 0x17, 0xE3, 0x40, 0xD5, 0x33, 0x55, 0xC0, 0xD5, 0x76, 0x92, 0x40, +0xFD, 0xD1, 0x3C, 0x40, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x72, 0xDC, 0xB0, +0x01, 0x75, 0x50, 0xC0, 0x02, 0x40, 0x49, 0xB0, 0x03, 0x55, 0x32, 0xC0, 0x04, 0x20, 0x2B, 0xB0, +0x05, 0x3E, 0x4F, 0x40, 0x06, 0x00, 0x0D, 0xB0, 0x07, 0x0B, 0xBC, 0x40, 0x07, 0xDF, 0xEF, 0xB0, +0x08, 0xFE, 0x13, 0x40, 0x09, 0xBF, 0xD1, 0xB0, 0x0A, 0xDD, 0xF5, 0x40, 0x0B, 0xA8, 0xEE, 0x30, +0x0C, 0xBD, 0xD7, 0x40, 0x0D, 0x88, 0xD0, 0x30, 0x0E, 0x9D, 0xB9, 0x40, 0x0F, 0x68, 0xB2, 0x30, +0x10, 0x86, 0xD5, 0xC0, 0x11, 0x48, 0x94, 0x30, 0x12, 0x66, 0xB7, 0xC0, 0x13, 0x28, 0x76, 0x30, +0x14, 0x46, 0x99, 0xC0, 0x15, 0x11, 0x92, 0xB0, 0x16, 0x26, 0x7B, 0xC0, 0x16, 0xF1, 0x74, 0xB0, +0x18, 0x06, 0x5D, 0xC0, 0x18, 0xD1, 0x56, 0xB0, 0x19, 0xE6, 0x3F, 0xC0, 0x1A, 0xB1, 0x38, 0xB0, +0x1B, 0xCF, 0x5C, 0x40, 0x1C, 0x91, 0x1A, 0xB0, 0x1D, 0xAF, 0x3E, 0x40, 0x1E, 0x70, 0xFC, 0xB0, +0x1F, 0x8F, 0x20, 0x40, 0x20, 0x7F, 0x03, 0x30, 0x21, 0x6F, 0x02, 0x40, 0x22, 0x39, 0xFB, 0x30, +0x23, 0x4E, 0xE4, 0x40, 0x24, 0x19, 0xDD, 0x30, 0x25, 0x38, 0x00, 0xC0, 0x25, 0xF9, 0xBF, 0x30, +0x26, 0xF2, 0xF8, 0xC0, 0x27, 0xD9, 0xA1, 0x30, 0x28, 0xF7, 0xC4, 0xC0, 0x29, 0xC2, 0xBD, 0xB0, +0x2A, 0xD7, 0xA6, 0xC0, 0x2B, 0xA2, 0x9F, 0xB0, 0x2C, 0xB7, 0x88, 0xC0, 0x2D, 0x82, 0x81, 0xB0, +0x2E, 0x97, 0x6A, 0xC0, 0x2F, 0x62, 0x63, 0xB0, 0x30, 0x80, 0x87, 0x40, 0x31, 0x42, 0x45, 0xB0, +0x32, 0x60, 0x69, 0x40, 0x33, 0x3D, 0xD7, 0x30, 0x34, 0x40, 0x4B, 0x40, 0x35, 0x0B, 0x44, 0x30, +0x36, 0x0D, 0xB8, 0x40, 0x37, 0x06, 0xD5, 0xB0, 0x38, 0x00, 0x0F, 0x40, 0x38, 0xCB, 0x08, 0x30, +0x39, 0xE9, 0x2B, 0xC0, 0x3A, 0xAA, 0xEA, 0x30, 0x3B, 0xC9, 0x0D, 0xC0, 0x3C, 0x8A, 0xCC, 0x30, +0x3D, 0xA8, 0xEF, 0xC0, 0x3E, 0x6A, 0xAE, 0x30, 0x3F, 0x88, 0xD1, 0xC0, 0x40, 0x53, 0xCA, 0xB0, +0x41, 0x68, 0xB3, 0xC0, 0x42, 0x33, 0xAC, 0xB0, 0x43, 0x48, 0x95, 0xC0, 0x44, 0x13, 0x8E, 0xB0, +0x45, 0x31, 0xB2, 0x40, 0x45, 0xF3, 0x70, 0xB0, 0x47, 0x11, 0x94, 0x40, 0x47, 0xEF, 0x02, 0x30, +0x48, 0xF1, 0x76, 0x40, 0x49, 0xBC, 0x6F, 0x30, 0x4A, 0xD1, 0x58, 0x40, 0x4B, 0xB8, 0x00, 0xB0, +0x4C, 0xB1, 0x3A, 0x40, 0x4D, 0xC6, 0x07, 0x30, 0x4E, 0x50, 0x82, 0xC0, 0x4F, 0x9C, 0xAE, 0xB0, +0x50, 0x42, 0xD9, 0xC0, 0x51, 0x7C, 0x90, 0xB0, 0x52, 0x2B, 0xF6, 0x40, 0x53, 0x5C, 0x72, 0xB0, +0x54, 0x0B, 0xD8, 0x40, 0x57, 0x37, 0xE6, 0x30, 0x57, 0xAF, 0xEC, 0xC0, 0x59, 0x17, 0xC8, 0x30, +0x59, 0x8F, 0xCE, 0xC0, 0x5A, 0xF7, 0xAA, 0x30, 0x5B, 0x6F, 0xB0, 0xC0, 0x5C, 0xA9, 0x67, 0xB0, +0x5D, 0x74, 0x7C, 0xC0, 0x5E, 0x89, 0x49, 0xB0, 0x5F, 0x54, 0x5E, 0xC0, 0x60, 0x69, 0x2B, 0xB0, +0x61, 0x34, 0x40, 0xC0, 0x62, 0x49, 0x0D, 0xB0, 0x63, 0x1D, 0x5D, 0x40, 0x64, 0x28, 0xEF, 0xB0, +0x64, 0xF4, 0x04, 0xC0, 0x66, 0x12, 0x0C, 0x30, 0x66, 0xDD, 0x21, 0x40, 0x67, 0xDB, 0x84, 0xB0, +0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, +0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, +0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, +0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, +0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, +0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, +0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, +0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, 0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, 0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, +0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, +0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, +0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, +0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, +0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, +0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, +0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, +0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x30, 0x80, 0x87, 0x40, 0x00, 0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x32, 0x60, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, +0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, +0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, +0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x47, 0x11, 0x94, 0x40, 0x00, 0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, +0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, 0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, +0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, +0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, +0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, +0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, +0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, +0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, +0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, +0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, +0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x43, +0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, 0x73, 0x65, 0x6E, 0x20, +0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -38062,8 +38289,8 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x38, -0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, -0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, +0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, +0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -47037,7 +47264,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -47068,7 +47295,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -65285,7 +65512,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -65316,7 +65543,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -70844,4 +71071,4 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { }; #endif -const timelib_tzdb timezonedb_builtin = { "2025.1", 597, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; +const timelib_tzdb timezonedb_builtin = { "2025.2", 598, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; From 22b2a579ba800f5572cabdad29017f4b9886768f Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 24 Mar 2025 10:06:34 +0000 Subject: [PATCH 155/503] Updated to version 2025.2 (2025b) --- ext/date/lib/timezonedb.h | 2251 ++++++++++++++++++++----------------- 1 file changed, 1239 insertions(+), 1012 deletions(-) diff --git a/ext/date/lib/timezonedb.h b/ext/date/lib/timezonedb.h index 3c75462009afb..a4cbb618799c8 100644 --- a/ext/date/lib/timezonedb.h +++ b/ext/date/lib/timezonedb.h @@ -4,7 +4,7 @@ #endif #ifdef TIMELIB_SUPPORT_SLIM_FILE -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x00008E }, { (char*) "Africa/Addis_Ababa" , 0x000356 }, @@ -104,508 +104,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x00ADD3 }, { (char*) "America/Cordoba" , 0x00AE74 }, { (char*) "America/Costa_Rica" , 0x00B144 }, - { (char*) "America/Creston" , 0x00B238 }, - { (char*) "America/Cuiaba" , 0x00B2F4 }, - { (char*) "America/Curacao" , 0x00B6B1 }, - { (char*) "America/Danmarkshavn" , 0x00B754 }, - { (char*) "America/Dawson" , 0x00B939 }, - { (char*) "America/Dawson_Creek" , 0x00BD5C }, - { (char*) "America/Denver" , 0x00C033 }, - { (char*) "America/Detroit" , 0x00C466 }, - { (char*) "America/Dominica" , 0x00C80E }, - { (char*) "America/Edmonton" , 0x00C89C }, - { (char*) "America/Eirunepe" , 0x00CC94 }, - { (char*) "America/El_Salvador" , 0x00CE63 }, - { (char*) "America/Ensenada" , 0x00CF1F }, - { (char*) "America/Fort_Nelson" , 0x00D362 }, - { (char*) "America/Fort_Wayne" , 0x00D92A }, - { (char*) "America/Fortaleza" , 0x00DB49 }, - { (char*) "America/Glace_Bay" , 0x00DD5F }, - { (char*) "America/Godthab" , 0x00E0F6 }, - { (char*) "America/Goose_Bay" , 0x00E4C7 }, - { (char*) "America/Grand_Turk" , 0x00EB1F }, - { (char*) "America/Grenada" , 0x00EE80 }, - { (char*) "America/Guadeloupe" , 0x00EF0E }, - { (char*) "America/Guatemala" , 0x00EF9C }, - { (char*) "America/Guayaquil" , 0x00F07C }, - { (char*) "America/Guyana" , 0x00F14D }, - { (char*) "America/Halifax" , 0x00F20E }, - { (char*) "America/Havana" , 0x00F8C0 }, - { (char*) "America/Hermosillo" , 0x00FD29 }, - { (char*) "America/Indiana/Indianapolis" , 0x00FE3D }, - { (char*) "America/Indiana/Knox" , 0x010075 }, - { (char*) "America/Indiana/Marengo" , 0x01048E }, - { (char*) "America/Indiana/Petersburg" , 0x0106E8 }, - { (char*) "America/Indiana/Tell_City" , 0x0109B2 }, - { (char*) "America/Indiana/Vevay" , 0x010BDC }, - { (char*) "America/Indiana/Vincennes" , 0x010D73 }, - { (char*) "America/Indiana/Winamac" , 0x010FC9 }, - { (char*) "America/Indianapolis" , 0x011246 }, - { (char*) "America/Inuvik" , 0x011465 }, - { (char*) "America/Iqaluit" , 0x0117B6 }, - { (char*) "America/Jamaica" , 0x011B32 }, - { (char*) "America/Jujuy" , 0x011C91 }, - { (char*) "America/Juneau" , 0x011F4F }, - { (char*) "America/Kentucky/Louisville" , 0x012335 }, - { (char*) "America/Kentucky/Monticello" , 0x012839 }, - { (char*) "America/Knox_IN" , 0x012C25 }, - { (char*) "America/Kralendijk" , 0x013029 }, - { (char*) "America/La_Paz" , 0x0130E6 }, - { (char*) "America/Lima" , 0x01319C }, - { (char*) "America/Los_Angeles" , 0x0132C3 }, - { (char*) "America/Louisville" , 0x0137E4 }, - { (char*) "America/Lower_Princes" , 0x013CCA }, - { (char*) "America/Maceio" , 0x013D87 }, - { (char*) "America/Managua" , 0x013F99 }, - { (char*) "America/Manaus" , 0x0140CC }, - { (char*) "America/Marigot" , 0x014283 }, - { (char*) "America/Martinique" , 0x014340 }, - { (char*) "America/Matamoros" , 0x0143FE }, - { (char*) "America/Mazatlan" , 0x0145EB }, - { (char*) "America/Mendoza" , 0x0148DB }, - { (char*) "America/Menominee" , 0x014BAB }, - { (char*) "America/Merida" , 0x014F6B }, - { (char*) "America/Metlakatla" , 0x015216 }, - { (char*) "America/Mexico_City" , 0x015483 }, - { (char*) "America/Miquelon" , 0x0157A2 }, - { (char*) "America/Moncton" , 0x0159D4 }, - { (char*) "America/Monterrey" , 0x015FCD }, - { (char*) "America/Montevideo" , 0x0162D4 }, - { (char*) "America/Montreal" , 0x0166A9 }, - { (char*) "America/Montserrat" , 0x016D6A }, - { (char*) "America/Nassau" , 0x016DF8 }, - { (char*) "America/New_York" , 0x0171F2 }, - { (char*) "America/Nipigon" , 0x0178E2 }, - { (char*) "America/Nome" , 0x017FA3 }, - { (char*) "America/Noronha" , 0x01838B }, - { (char*) "America/North_Dakota/Beulah" , 0x01858B }, - { (char*) "America/North_Dakota/Center" , 0x0189BF }, - { (char*) "America/North_Dakota/New_Salem" , 0x018DBE }, - { (char*) "America/Nuuk" , 0x0191C3 }, - { (char*) "America/Ojinaga" , 0x0195A5 }, - { (char*) "America/Panama" , 0x01989B }, - { (char*) "America/Pangnirtung" , 0x01993C }, - { (char*) "America/Paramaribo" , 0x019C9F }, - { (char*) "America/Phoenix" , 0x019D66 }, - { (char*) "America/Port-au-Prince" , 0x019E7A }, - { (char*) "America/Port_of_Spain" , 0x01A0BB }, - { (char*) "America/Porto_Acre" , 0x01A149 }, - { (char*) "America/Porto_Velho" , 0x01A2F7 }, - { (char*) "America/Puerto_Rico" , 0x01A495 }, - { (char*) "America/Punta_Arenas" , 0x01A552 }, - { (char*) "America/Rainy_River" , 0x01AA34 }, - { (char*) "America/Rankin_Inlet" , 0x01AF4E }, - { (char*) "America/Recife" , 0x01B297 }, - { (char*) "America/Regina" , 0x01B491 }, - { (char*) "America/Resolute" , 0x01B730 }, - { (char*) "America/Rio_Branco" , 0x01BA7A }, - { (char*) "America/Rosario" , 0x01BC2C }, - { (char*) "America/Santa_Isabel" , 0x01BEFC }, - { (char*) "America/Santarem" , 0x01C33F }, - { (char*) "America/Santiago" , 0x01C4EF }, - { (char*) "America/Santo_Domingo" , 0x01CA52 }, - { (char*) "America/Sao_Paulo" , 0x01CB9B }, - { (char*) "America/Scoresbysund" , 0x01CF95 }, - { (char*) "America/Shiprock" , 0x01D396 }, - { (char*) "America/Sitka" , 0x01D7B4 }, - { (char*) "America/St_Barthelemy" , 0x01DB8F }, - { (char*) "America/St_Johns" , 0x01DC4C }, - { (char*) "America/St_Kitts" , 0x01E3C9 }, - { (char*) "America/St_Lucia" , 0x01E457 }, - { (char*) "America/St_Thomas" , 0x01E4F8 }, - { (char*) "America/St_Vincent" , 0x01E586 }, - { (char*) "America/Swift_Current" , 0x01E627 }, - { (char*) "America/Tegucigalpa" , 0x01E7B5 }, - { (char*) "America/Thule" , 0x01E883 }, - { (char*) "America/Thunder_Bay" , 0x01EA64 }, - { (char*) "America/Tijuana" , 0x01F125 }, - { (char*) "America/Toronto" , 0x01F577 }, - { (char*) "America/Tortola" , 0x01FC56 }, - { (char*) "America/Vancouver" , 0x01FCE4 }, - { (char*) "America/Virgin" , 0x02023B }, - { (char*) "America/Whitehorse" , 0x0202F8 }, - { (char*) "America/Winnipeg" , 0x02071B }, - { (char*) "America/Yakutat" , 0x020C52 }, - { (char*) "America/Yellowknife" , 0x021020 }, - { (char*) "Antarctica/Casey" , 0x0213F6 }, - { (char*) "Antarctica/Davis" , 0x021526 }, - { (char*) "Antarctica/DumontDUrville" , 0x0215FC }, - { (char*) "Antarctica/Macquarie" , 0x0216B0 }, - { (char*) "Antarctica/Mawson" , 0x021A9C }, - { (char*) "Antarctica/McMurdo" , 0x021B46 }, - { (char*) "Antarctica/Palmer" , 0x021E78 }, - { (char*) "Antarctica/Rothera" , 0x022201 }, - { (char*) "Antarctica/South_Pole" , 0x022298 }, - { (char*) "Antarctica/Syowa" , 0x0226B7 }, - { (char*) "Antarctica/Troll" , 0x02274D }, - { (char*) "Antarctica/Vostok" , 0x0227FC }, - { (char*) "Arctic/Longyearbyen" , 0x0228B8 }, - { (char*) "Asia/Aden" , 0x022B85 }, - { (char*) "Asia/Almaty" , 0x022C16 }, - { (char*) "Asia/Amman" , 0x022E9E }, - { (char*) "Asia/Anadyr" , 0x02324A }, - { (char*) "Asia/Aqtau" , 0x023550 }, - { (char*) "Asia/Aqtobe" , 0x0237CF }, - { (char*) "Asia/Ashgabat" , 0x023A4F }, - { (char*) "Asia/Ashkhabad" , 0x023BD2 }, - { (char*) "Asia/Atyrau" , 0x023D55 }, - { (char*) "Asia/Baghdad" , 0x023FDE }, - { (char*) "Asia/Bahrain" , 0x024260 }, - { (char*) "Asia/Baku" , 0x024319 }, - { (char*) "Asia/Bangkok" , 0x02460D }, - { (char*) "Asia/Barnaul" , 0x0246B1 }, - { (char*) "Asia/Beirut" , 0x0249BC }, - { (char*) "Asia/Bishkek" , 0x024CA4 }, - { (char*) "Asia/Brunei" , 0x024F1A }, - { (char*) "Asia/Calcutta" , 0x024FC0 }, - { (char*) "Asia/Chita" , 0x0250A8 }, - { (char*) "Asia/Choibalsan" , 0x0253B6 }, - { (char*) "Asia/Chongqing" , 0x025614 }, - { (char*) "Asia/Chungking" , 0x0257A9 }, - { (char*) "Asia/Colombo" , 0x02593E }, - { (char*) "Asia/Dacca" , 0x025A41 }, - { (char*) "Asia/Damascus" , 0x025B34 }, - { (char*) "Asia/Dhaka" , 0x026012 }, - { (char*) "Asia/Dili" , 0x026105 }, - { (char*) "Asia/Dubai" , 0x0261BB }, - { (char*) "Asia/Dushanbe" , 0x02624C }, - { (char*) "Asia/Famagusta" , 0x0263C6 }, - { (char*) "Asia/Gaza" , 0x02678D }, - { (char*) "Asia/Harbin" , 0x027329 }, - { (char*) "Asia/Hebron" , 0x0274BE }, - { (char*) "Asia/Ho_Chi_Minh" , 0x02806B }, - { (char*) "Asia/Hong_Kong" , 0x028163 }, - { (char*) "Asia/Hovd" , 0x028476 }, - { (char*) "Asia/Irkutsk" , 0x0286EA }, - { (char*) "Asia/Istanbul" , 0x028A08 }, - { (char*) "Asia/Jakarta" , 0x028EC4 }, - { (char*) "Asia/Jayapura" , 0x028FD5 }, - { (char*) "Asia/Jerusalem" , 0x0290C2 }, - { (char*) "Asia/Kabul" , 0x029500 }, - { (char*) "Asia/Kamchatka" , 0x0295AB }, - { (char*) "Asia/Karachi" , 0x0298A0 }, - { (char*) "Asia/Kashgar" , 0x0299B6 }, - { (char*) "Asia/Kathmandu" , 0x029A47 }, - { (char*) "Asia/Katmandu" , 0x029AF4 }, - { (char*) "Asia/Khandyga" , 0x029BA1 }, - { (char*) "Asia/Kolkata" , 0x029ED2 }, - { (char*) "Asia/Krasnoyarsk" , 0x029FBA }, - { (char*) "Asia/Kuala_Lumpur" , 0x02A2C4 }, - { (char*) "Asia/Kuching" , 0x02A3E4 }, - { (char*) "Asia/Kuwait" , 0x02A53E }, - { (char*) "Asia/Macao" , 0x02A5CF }, - { (char*) "Asia/Macau" , 0x02A8F2 }, - { (char*) "Asia/Magadan" , 0x02AC15 }, - { (char*) "Asia/Makassar" , 0x02AF20 }, - { (char*) "Asia/Manila" , 0x02B033 }, - { (char*) "Asia/Muscat" , 0x02B151 }, - { (char*) "Asia/Nicosia" , 0x02B1E2 }, - { (char*) "Asia/Novokuznetsk" , 0x02B451 }, - { (char*) "Asia/Novosibirsk" , 0x02B744 }, - { (char*) "Asia/Omsk" , 0x02BA55 }, - { (char*) "Asia/Oral" , 0x02BD53 }, - { (char*) "Asia/Phnom_Penh" , 0x02BFDF }, - { (char*) "Asia/Pontianak" , 0x02C0B3 }, - { (char*) "Asia/Pyongyang" , 0x02C1CC }, - { (char*) "Asia/Qatar" , 0x02C28F }, - { (char*) "Asia/Qostanay" , 0x02C333 }, - { (char*) "Asia/Qyzylorda" , 0x02C5C9 }, - { (char*) "Asia/Rangoon" , 0x02C862 }, - { (char*) "Asia/Riyadh" , 0x02C929 }, - { (char*) "Asia/Saigon" , 0x02C9BA }, - { (char*) "Asia/Sakhalin" , 0x02CAB2 }, - { (char*) "Asia/Samarkand" , 0x02CDC9 }, - { (char*) "Asia/Seoul" , 0x02CF54 }, - { (char*) "Asia/Shanghai" , 0x02D0FF }, - { (char*) "Asia/Singapore" , 0x02D2A0 }, - { (char*) "Asia/Srednekolymsk" , 0x02D3AC }, - { (char*) "Asia/Taipei" , 0x02D6BC }, - { (char*) "Asia/Tashkent" , 0x02D8C7 }, - { (char*) "Asia/Tbilisi" , 0x02DA52 }, - { (char*) "Asia/Tehran" , 0x02DCD3 }, - { (char*) "Asia/Tel_Aviv" , 0x02E00B }, - { (char*) "Asia/Thimbu" , 0x02E449 }, - { (char*) "Asia/Thimphu" , 0x02E4EF }, - { (char*) "Asia/Tokyo" , 0x02E595 }, - { (char*) "Asia/Tomsk" , 0x02E676 }, - { (char*) "Asia/Ujung_Pandang" , 0x02E981 }, - { (char*) "Asia/Ulaanbaatar" , 0x02EA4B }, - { (char*) "Asia/Ulan_Bator" , 0x02ECB9 }, - { (char*) "Asia/Urumqi" , 0x02EF17 }, - { (char*) "Asia/Ust-Nera" , 0x02EFB5 }, - { (char*) "Asia/Vientiane" , 0x02F2D8 }, - { (char*) "Asia/Vladivostok" , 0x02F3BE }, - { (char*) "Asia/Yakutsk" , 0x02F6C3 }, - { (char*) "Asia/Yangon" , 0x02F9C7 }, - { (char*) "Asia/Yekaterinburg" , 0x02FA8E }, - { (char*) "Asia/Yerevan" , 0x02FDA0 }, - { (char*) "Atlantic/Azores" , 0x030070 }, - { (char*) "Atlantic/Bermuda" , 0x0305FB }, - { (char*) "Atlantic/Canary" , 0x030A07 }, - { (char*) "Atlantic/Cape_Verde" , 0x030BFF }, - { (char*) "Atlantic/Faeroe" , 0x030CBA }, - { (char*) "Atlantic/Faroe" , 0x030E7F }, - { (char*) "Atlantic/Jan_Mayen" , 0x031044 }, - { (char*) "Atlantic/Madeira" , 0x031311 }, - { (char*) "Atlantic/Reykjavik" , 0x031888 }, - { (char*) "Atlantic/South_Georgia" , 0x031B85 }, - { (char*) "Atlantic/St_Helena" , 0x031C15 }, - { (char*) "Atlantic/Stanley" , 0x031CB6 }, - { (char*) "Australia/ACT" , 0x031FD7 }, - { (char*) "Australia/Adelaide" , 0x03236B }, - { (char*) "Australia/Brisbane" , 0x03271F }, - { (char*) "Australia/Broken_Hill" , 0x032863 }, - { (char*) "Australia/Canberra" , 0x032C38 }, - { (char*) "Australia/Currie" , 0x032FCC }, - { (char*) "Australia/Darwin" , 0x0333C3 }, - { (char*) "Australia/Eucla" , 0x0334CB }, - { (char*) "Australia/Hobart" , 0x03362A }, - { (char*) "Australia/LHI" , 0x033A29 }, - { (char*) "Australia/Lindeman" , 0x033CE9 }, - { (char*) "Australia/Lord_Howe" , 0x033E59 }, - { (char*) "Australia/Melbourne" , 0x034129 }, - { (char*) "Australia/North" , 0x0344C5 }, - { (char*) "Australia/NSW" , 0x0345BB }, - { (char*) "Australia/Perth" , 0x03494F }, - { (char*) "Australia/Queensland" , 0x034AAB }, - { (char*) "Australia/South" , 0x034BD8 }, - { (char*) "Australia/Sydney" , 0x034F7D }, - { (char*) "Australia/Tasmania" , 0x03532D }, - { (char*) "Australia/Victoria" , 0x035724 }, - { (char*) "Australia/West" , 0x035AB8 }, - { (char*) "Australia/Yancowinna" , 0x035BF6 }, - { (char*) "Brazil/Acre" , 0x035FAF }, - { (char*) "Brazil/DeNoronha" , 0x03615D }, - { (char*) "Brazil/East" , 0x03634D }, - { (char*) "Brazil/West" , 0x036711 }, - { (char*) "Canada/Atlantic" , 0x0368B9 }, - { (char*) "Canada/Central" , 0x036F4D }, - { (char*) "Canada/Eastern" , 0x037467 }, - { (char*) "Canada/Mountain" , 0x037B28 }, - { (char*) "Canada/Newfoundland" , 0x037EFE }, - { (char*) "Canada/Pacific" , 0x038660 }, - { (char*) "Canada/Saskatchewan" , 0x038B9E }, - { (char*) "Canada/Yukon" , 0x038E28 }, - { (char*) "CET" , 0x039239 }, - { (char*) "Chile/Continental" , 0x039694 }, - { (char*) "Chile/EasterIsland" , 0x039BEA }, - { (char*) "CST6CDT" , 0x03A08C }, - { (char*) "Cuba" , 0x03A772 }, - { (char*) "EET" , 0x03ABDB }, - { (char*) "Egypt" , 0x03AE91 }, - { (char*) "Eire" , 0x03B3BA }, - { (char*) "EST" , 0x03B99E }, - { (char*) "EST5EDT" , 0x03BA3F }, - { (char*) "Etc/GMT" , 0x03C11B }, - { (char*) "Etc/GMT+0" , 0x03C196 }, - { (char*) "Etc/GMT+1" , 0x03C211 }, - { (char*) "Etc/GMT+10" , 0x03C28E }, - { (char*) "Etc/GMT+11" , 0x03C30C }, - { (char*) "Etc/GMT+12" , 0x03C38A }, - { (char*) "Etc/GMT+2" , 0x03C408 }, - { (char*) "Etc/GMT+3" , 0x03C485 }, - { (char*) "Etc/GMT+4" , 0x03C502 }, - { (char*) "Etc/GMT+5" , 0x03C57F }, - { (char*) "Etc/GMT+6" , 0x03C5FC }, - { (char*) "Etc/GMT+7" , 0x03C679 }, - { (char*) "Etc/GMT+8" , 0x03C6F6 }, - { (char*) "Etc/GMT+9" , 0x03C773 }, - { (char*) "Etc/GMT-0" , 0x03C7F0 }, - { (char*) "Etc/GMT-1" , 0x03C86B }, - { (char*) "Etc/GMT-10" , 0x03C8E9 }, - { (char*) "Etc/GMT-11" , 0x03C968 }, - { (char*) "Etc/GMT-12" , 0x03C9E7 }, - { (char*) "Etc/GMT-13" , 0x03CA66 }, - { (char*) "Etc/GMT-14" , 0x03CAE5 }, - { (char*) "Etc/GMT-2" , 0x03CB64 }, - { (char*) "Etc/GMT-3" , 0x03CBE2 }, - { (char*) "Etc/GMT-4" , 0x03CC60 }, - { (char*) "Etc/GMT-5" , 0x03CCDE }, - { (char*) "Etc/GMT-6" , 0x03CD5C }, - { (char*) "Etc/GMT-7" , 0x03CDDA }, - { (char*) "Etc/GMT-8" , 0x03CE58 }, - { (char*) "Etc/GMT-9" , 0x03CED6 }, - { (char*) "Etc/GMT0" , 0x03CF54 }, - { (char*) "Etc/Greenwich" , 0x03CFCF }, - { (char*) "Etc/UCT" , 0x03D04A }, - { (char*) "Etc/Universal" , 0x03D0C5 }, - { (char*) "Etc/UTC" , 0x03D140 }, - { (char*) "Etc/Zulu" , 0x03D1BB }, - { (char*) "Europe/Amsterdam" , 0x03D236 }, - { (char*) "Europe/Andorra" , 0x03D671 }, - { (char*) "Europe/Astrakhan" , 0x03D802 }, - { (char*) "Europe/Athens" , 0x03DAF6 }, - { (char*) "Europe/Belfast" , 0x03DDAC }, - { (char*) "Europe/Belgrade" , 0x03E3F7 }, - { (char*) "Europe/Berlin" , 0x03E5E1 }, - { (char*) "Europe/Bratislava" , 0x03E8BD }, - { (char*) "Europe/Brussels" , 0x03EB9C }, - { (char*) "Europe/Bucharest" , 0x03EFF7 }, - { (char*) "Europe/Budapest" , 0x03F298 }, - { (char*) "Europe/Busingen" , 0x03F5A2 }, - { (char*) "Europe/Chisinau" , 0x03F7A7 }, - { (char*) "Europe/Copenhagen" , 0x03FAA6 }, - { (char*) "Europe/Dublin" , 0x03FD21 }, - { (char*) "Europe/Gibraltar" , 0x040305 }, - { (char*) "Europe/Guernsey" , 0x0407D5 }, - { (char*) "Europe/Helsinki" , 0x040E2C }, - { (char*) "Europe/Isle_of_Man" , 0x041019 }, - { (char*) "Europe/Istanbul" , 0x041664 }, - { (char*) "Europe/Jersey" , 0x041B20 }, - { (char*) "Europe/Kaliningrad" , 0x042177 }, - { (char*) "Europe/Kiev" , 0x04251F }, - { (char*) "Europe/Kirov" , 0x042759 }, - { (char*) "Europe/Kyiv" , 0x042A52 }, - { (char*) "Europe/Lisbon" , 0x042C9B }, - { (char*) "Europe/Ljubljana" , 0x043271 }, - { (char*) "Europe/London" , 0x04345B }, - { (char*) "Europe/Luxembourg" , 0x043AA6 }, - { (char*) "Europe/Madrid" , 0x043EF1 }, - { (char*) "Europe/Malta" , 0x04428E }, - { (char*) "Europe/Mariehamn" , 0x04463A }, - { (char*) "Europe/Minsk" , 0x044827 }, - { (char*) "Europe/Monaco" , 0x044B5B }, - { (char*) "Europe/Moscow" , 0x044FC1 }, - { (char*) "Europe/Nicosia" , 0x04536D }, - { (char*) "Europe/Oslo" , 0x0455CE }, - { (char*) "Europe/Paris" , 0x04587E }, - { (char*) "Europe/Podgorica" , 0x045CDB }, - { (char*) "Europe/Prague" , 0x045EC5 }, - { (char*) "Europe/Riga" , 0x0461A4 }, - { (char*) "Europe/Rome" , 0x046466 }, - { (char*) "Europe/Samara" , 0x046825 }, - { (char*) "Europe/San_Marino" , 0x046B26 }, - { (char*) "Europe/Sarajevo" , 0x046EE5 }, - { (char*) "Europe/Saratov" , 0x0470CF }, - { (char*) "Europe/Simferopol" , 0x0473C1 }, - { (char*) "Europe/Skopje" , 0x047734 }, - { (char*) "Europe/Sofia" , 0x04791E }, - { (char*) "Europe/Stockholm" , 0x047B7A }, - { (char*) "Europe/Tallinn" , 0x047D77 }, - { (char*) "Europe/Tirane" , 0x048026 }, - { (char*) "Europe/Tiraspol" , 0x04828E }, - { (char*) "Europe/Ulyanovsk" , 0x04858D }, - { (char*) "Europe/Uzhgorod" , 0x0488A3 }, - { (char*) "Europe/Vaduz" , 0x048ADD }, - { (char*) "Europe/Vatican" , 0x048CC7 }, - { (char*) "Europe/Vienna" , 0x049086 }, - { (char*) "Europe/Vilnius" , 0x049324 }, - { (char*) "Europe/Volgograd" , 0x0495D4 }, - { (char*) "Europe/Warsaw" , 0x0498E3 }, - { (char*) "Europe/Zagreb" , 0x049C8A }, - { (char*) "Europe/Zaporozhye" , 0x049E74 }, - { (char*) "Europe/Zurich" , 0x04A0AE }, - { (char*) "Factory" , 0x04A2AB }, - { (char*) "GB" , 0x04A328 }, - { (char*) "GB-Eire" , 0x04A973 }, - { (char*) "GMT" , 0x04AFBE }, - { (char*) "GMT+0" , 0x04B039 }, - { (char*) "GMT-0" , 0x04B0B4 }, - { (char*) "GMT0" , 0x04B12F }, - { (char*) "Greenwich" , 0x04B1AA }, - { (char*) "Hongkong" , 0x04B225 }, - { (char*) "HST" , 0x04B538 }, - { (char*) "Iceland" , 0x04B621 }, - { (char*) "Indian/Antananarivo" , 0x04B6AF }, - { (char*) "Indian/Chagos" , 0x04B75B }, - { (char*) "Indian/Christmas" , 0x04B7FF }, - { (char*) "Indian/Cocos" , 0x04B890 }, - { (char*) "Indian/Comoro" , 0x04B928 }, - { (char*) "Indian/Kerguelen" , 0x04B9B7 }, - { (char*) "Indian/Mahe" , 0x04BA48 }, - { (char*) "Indian/Maldives" , 0x04BAD9 }, - { (char*) "Indian/Mauritius" , 0x04BB7D }, - { (char*) "Indian/Mayotte" , 0x04BC3C }, - { (char*) "Indian/Reunion" , 0x04BCCB }, - { (char*) "Iran" , 0x04BD5C }, - { (char*) "Israel" , 0x04C094 }, - { (char*) "Jamaica" , 0x04C4D2 }, - { (char*) "Japan" , 0x04C631 }, - { (char*) "Kwajalein" , 0x04C712 }, - { (char*) "Libya" , 0x04C7F9 }, - { (char*) "MET" , 0x04C9B4 }, - { (char*) "Mexico/BajaNorte" , 0x04CE0F }, - { (char*) "Mexico/BajaSur" , 0x04D252 }, - { (char*) "Mexico/General" , 0x04D510 }, - { (char*) "MST" , 0x04D821 }, - { (char*) "MST7MDT" , 0x04D91D }, - { (char*) "Navajo" , 0x04DD3B }, - { (char*) "NZ" , 0x04E159 }, - { (char*) "NZ-CHAT" , 0x04E578 }, - { (char*) "Pacific/Apia" , 0x04E8AC }, - { (char*) "Pacific/Auckland" , 0x04EA4F }, - { (char*) "Pacific/Bougainville" , 0x04EE81 }, - { (char*) "Pacific/Chatham" , 0x04EF62 }, - { (char*) "Pacific/Chuuk" , 0x04F2A5 }, - { (char*) "Pacific/Easter" , 0x04F383 }, - { (char*) "Pacific/Efate" , 0x04F832 }, - { (char*) "Pacific/Enderbury" , 0x04F994 }, - { (char*) "Pacific/Fakaofo" , 0x04FA4C }, - { (char*) "Pacific/Fiji" , 0x04FAF1 }, - { (char*) "Pacific/Funafuti" , 0x04FC89 }, - { (char*) "Pacific/Galapagos" , 0x04FD1B }, - { (char*) "Pacific/Gambier" , 0x04FDE7 }, - { (char*) "Pacific/Guadalcanal" , 0x04FE86 }, - { (char*) "Pacific/Guam" , 0x04FF18 }, - { (char*) "Pacific/Honolulu" , 0x050082 }, - { (char*) "Pacific/Johnston" , 0x050171 }, - { (char*) "Pacific/Kanton" , 0x05025A }, - { (char*) "Pacific/Kiritimati" , 0x050321 }, - { (char*) "Pacific/Kosrae" , 0x0503E7 }, - { (char*) "Pacific/Kwajalein" , 0x0504EB }, - { (char*) "Pacific/Majuro" , 0x0505DB }, - { (char*) "Pacific/Marquesas" , 0x0506D9 }, - { (char*) "Pacific/Midway" , 0x050781 }, - { (char*) "Pacific/Nauru" , 0x050844 }, - { (char*) "Pacific/Niue" , 0x050907 }, - { (char*) "Pacific/Norfolk" , 0x0509AD }, - { (char*) "Pacific/Noumea" , 0x050AA6 }, - { (char*) "Pacific/Pago_Pago" , 0x050B78 }, - { (char*) "Pacific/Palau" , 0x050C16 }, - { (char*) "Pacific/Pitcairn" , 0x050CB6 }, - { (char*) "Pacific/Pohnpei" , 0x050D5B }, - { (char*) "Pacific/Ponape" , 0x050E4B }, - { (char*) "Pacific/Port_Moresby" , 0x050EDD }, - { (char*) "Pacific/Rarotonga" , 0x050F9B }, - { (char*) "Pacific/Saipan" , 0x05113D }, - { (char*) "Pacific/Samoa" , 0x05129E }, - { (char*) "Pacific/Tahiti" , 0x05133C }, - { (char*) "Pacific/Tarawa" , 0x0513DC }, - { (char*) "Pacific/Tongatapu" , 0x05147D }, - { (char*) "Pacific/Truk" , 0x051576 }, - { (char*) "Pacific/Wake" , 0x05161C }, - { (char*) "Pacific/Wallis" , 0x0516B9 }, - { (char*) "Pacific/Yap" , 0x05174B }, - { (char*) "Poland" , 0x0517F1 }, - { (char*) "Portugal" , 0x051B98 }, - { (char*) "PRC" , 0x05215B }, - { (char*) "PST8PDT" , 0x0522F0 }, - { (char*) "ROC" , 0x05280A }, - { (char*) "ROK" , 0x052A15 }, - { (char*) "Singapore" , 0x052BC0 }, - { (char*) "Turkey" , 0x052CCC }, - { (char*) "UCT" , 0x053188 }, - { (char*) "Universal" , 0x053203 }, - { (char*) "US/Alaska" , 0x05327E }, - { (char*) "US/Aleutian" , 0x05365B }, - { (char*) "US/Arizona" , 0x053A30 }, - { (char*) "US/Central" , 0x053B2C }, - { (char*) "US/East-Indiana" , 0x054212 }, - { (char*) "US/Eastern" , 0x054431 }, - { (char*) "US/Hawaii" , 0x054B0D }, - { (char*) "US/Indiana-Starke" , 0x054BF6 }, - { (char*) "US/Michigan" , 0x054FFA }, - { (char*) "US/Mountain" , 0x055389 }, - { (char*) "US/Pacific" , 0x0557A7 }, - { (char*) "US/Samoa" , 0x055CC1 }, - { (char*) "UTC" , 0x055D5F }, - { (char*) "W-SU" , 0x055DDA }, - { (char*) "WET" , 0x056172 }, - { (char*) "Zulu" , 0x056735 }, + { (char*) "America/Coyhaique" , 0x00B238 }, + { (char*) "America/Creston" , 0x00B7A2 }, + { (char*) "America/Cuiaba" , 0x00B85E }, + { (char*) "America/Curacao" , 0x00BC1B }, + { (char*) "America/Danmarkshavn" , 0x00BCBE }, + { (char*) "America/Dawson" , 0x00BEA3 }, + { (char*) "America/Dawson_Creek" , 0x00C2C6 }, + { (char*) "America/Denver" , 0x00C59D }, + { (char*) "America/Detroit" , 0x00C9D0 }, + { (char*) "America/Dominica" , 0x00CD78 }, + { (char*) "America/Edmonton" , 0x00CE06 }, + { (char*) "America/Eirunepe" , 0x00D1FE }, + { (char*) "America/El_Salvador" , 0x00D3CD }, + { (char*) "America/Ensenada" , 0x00D489 }, + { (char*) "America/Fort_Nelson" , 0x00D8CC }, + { (char*) "America/Fort_Wayne" , 0x00DE94 }, + { (char*) "America/Fortaleza" , 0x00E0B3 }, + { (char*) "America/Glace_Bay" , 0x00E2C9 }, + { (char*) "America/Godthab" , 0x00E660 }, + { (char*) "America/Goose_Bay" , 0x00EA31 }, + { (char*) "America/Grand_Turk" , 0x00F089 }, + { (char*) "America/Grenada" , 0x00F3EA }, + { (char*) "America/Guadeloupe" , 0x00F478 }, + { (char*) "America/Guatemala" , 0x00F506 }, + { (char*) "America/Guayaquil" , 0x00F5E6 }, + { (char*) "America/Guyana" , 0x00F6B7 }, + { (char*) "America/Halifax" , 0x00F778 }, + { (char*) "America/Havana" , 0x00FE2A }, + { (char*) "America/Hermosillo" , 0x010293 }, + { (char*) "America/Indiana/Indianapolis" , 0x0103A7 }, + { (char*) "America/Indiana/Knox" , 0x0105DF }, + { (char*) "America/Indiana/Marengo" , 0x0109F8 }, + { (char*) "America/Indiana/Petersburg" , 0x010C52 }, + { (char*) "America/Indiana/Tell_City" , 0x010F1C }, + { (char*) "America/Indiana/Vevay" , 0x011146 }, + { (char*) "America/Indiana/Vincennes" , 0x0112DD }, + { (char*) "America/Indiana/Winamac" , 0x011533 }, + { (char*) "America/Indianapolis" , 0x0117B0 }, + { (char*) "America/Inuvik" , 0x0119CF }, + { (char*) "America/Iqaluit" , 0x011D20 }, + { (char*) "America/Jamaica" , 0x01209C }, + { (char*) "America/Jujuy" , 0x0121FB }, + { (char*) "America/Juneau" , 0x0124B9 }, + { (char*) "America/Kentucky/Louisville" , 0x01289F }, + { (char*) "America/Kentucky/Monticello" , 0x012DA3 }, + { (char*) "America/Knox_IN" , 0x01318F }, + { (char*) "America/Kralendijk" , 0x013593 }, + { (char*) "America/La_Paz" , 0x013650 }, + { (char*) "America/Lima" , 0x013706 }, + { (char*) "America/Los_Angeles" , 0x01382D }, + { (char*) "America/Louisville" , 0x013D4E }, + { (char*) "America/Lower_Princes" , 0x014234 }, + { (char*) "America/Maceio" , 0x0142F1 }, + { (char*) "America/Managua" , 0x014503 }, + { (char*) "America/Manaus" , 0x014636 }, + { (char*) "America/Marigot" , 0x0147ED }, + { (char*) "America/Martinique" , 0x0148AA }, + { (char*) "America/Matamoros" , 0x014968 }, + { (char*) "America/Mazatlan" , 0x014B55 }, + { (char*) "America/Mendoza" , 0x014E45 }, + { (char*) "America/Menominee" , 0x015115 }, + { (char*) "America/Merida" , 0x0154D5 }, + { (char*) "America/Metlakatla" , 0x015780 }, + { (char*) "America/Mexico_City" , 0x0159ED }, + { (char*) "America/Miquelon" , 0x015D0C }, + { (char*) "America/Moncton" , 0x015F3E }, + { (char*) "America/Monterrey" , 0x016537 }, + { (char*) "America/Montevideo" , 0x01683E }, + { (char*) "America/Montreal" , 0x016C13 }, + { (char*) "America/Montserrat" , 0x0172D4 }, + { (char*) "America/Nassau" , 0x017362 }, + { (char*) "America/New_York" , 0x01775C }, + { (char*) "America/Nipigon" , 0x017E4C }, + { (char*) "America/Nome" , 0x01850D }, + { (char*) "America/Noronha" , 0x0188F5 }, + { (char*) "America/North_Dakota/Beulah" , 0x018AF5 }, + { (char*) "America/North_Dakota/Center" , 0x018F29 }, + { (char*) "America/North_Dakota/New_Salem" , 0x019328 }, + { (char*) "America/Nuuk" , 0x01972D }, + { (char*) "America/Ojinaga" , 0x019B0F }, + { (char*) "America/Panama" , 0x019E05 }, + { (char*) "America/Pangnirtung" , 0x019EA6 }, + { (char*) "America/Paramaribo" , 0x01A209 }, + { (char*) "America/Phoenix" , 0x01A2D0 }, + { (char*) "America/Port-au-Prince" , 0x01A3E4 }, + { (char*) "America/Port_of_Spain" , 0x01A625 }, + { (char*) "America/Porto_Acre" , 0x01A6B3 }, + { (char*) "America/Porto_Velho" , 0x01A861 }, + { (char*) "America/Puerto_Rico" , 0x01A9FF }, + { (char*) "America/Punta_Arenas" , 0x01AABC }, + { (char*) "America/Rainy_River" , 0x01AF9B }, + { (char*) "America/Rankin_Inlet" , 0x01B4B5 }, + { (char*) "America/Recife" , 0x01B7FE }, + { (char*) "America/Regina" , 0x01B9F8 }, + { (char*) "America/Resolute" , 0x01BC97 }, + { (char*) "America/Rio_Branco" , 0x01BFE1 }, + { (char*) "America/Rosario" , 0x01C193 }, + { (char*) "America/Santa_Isabel" , 0x01C463 }, + { (char*) "America/Santarem" , 0x01C8A6 }, + { (char*) "America/Santiago" , 0x01CA56 }, + { (char*) "America/Santo_Domingo" , 0x01CFB9 }, + { (char*) "America/Sao_Paulo" , 0x01D102 }, + { (char*) "America/Scoresbysund" , 0x01D4FC }, + { (char*) "America/Shiprock" , 0x01D8FD }, + { (char*) "America/Sitka" , 0x01DD1B }, + { (char*) "America/St_Barthelemy" , 0x01E0F6 }, + { (char*) "America/St_Johns" , 0x01E1B3 }, + { (char*) "America/St_Kitts" , 0x01E930 }, + { (char*) "America/St_Lucia" , 0x01E9BE }, + { (char*) "America/St_Thomas" , 0x01EA5F }, + { (char*) "America/St_Vincent" , 0x01EAED }, + { (char*) "America/Swift_Current" , 0x01EB8E }, + { (char*) "America/Tegucigalpa" , 0x01ED1C }, + { (char*) "America/Thule" , 0x01EDEA }, + { (char*) "America/Thunder_Bay" , 0x01EFCB }, + { (char*) "America/Tijuana" , 0x01F68C }, + { (char*) "America/Toronto" , 0x01FADE }, + { (char*) "America/Tortola" , 0x0201BD }, + { (char*) "America/Vancouver" , 0x02024B }, + { (char*) "America/Virgin" , 0x0207A2 }, + { (char*) "America/Whitehorse" , 0x02085F }, + { (char*) "America/Winnipeg" , 0x020C82 }, + { (char*) "America/Yakutat" , 0x0211B9 }, + { (char*) "America/Yellowknife" , 0x021587 }, + { (char*) "Antarctica/Casey" , 0x02195D }, + { (char*) "Antarctica/Davis" , 0x021A8D }, + { (char*) "Antarctica/DumontDUrville" , 0x021B63 }, + { (char*) "Antarctica/Macquarie" , 0x021C17 }, + { (char*) "Antarctica/Mawson" , 0x022003 }, + { (char*) "Antarctica/McMurdo" , 0x0220AD }, + { (char*) "Antarctica/Palmer" , 0x0223DF }, + { (char*) "Antarctica/Rothera" , 0x022768 }, + { (char*) "Antarctica/South_Pole" , 0x0227FF }, + { (char*) "Antarctica/Syowa" , 0x022C1E }, + { (char*) "Antarctica/Troll" , 0x022CB4 }, + { (char*) "Antarctica/Vostok" , 0x022D63 }, + { (char*) "Arctic/Longyearbyen" , 0x022E1F }, + { (char*) "Asia/Aden" , 0x0230EC }, + { (char*) "Asia/Almaty" , 0x02317D }, + { (char*) "Asia/Amman" , 0x023405 }, + { (char*) "Asia/Anadyr" , 0x0237B1 }, + { (char*) "Asia/Aqtau" , 0x023AB7 }, + { (char*) "Asia/Aqtobe" , 0x023D36 }, + { (char*) "Asia/Ashgabat" , 0x023FB6 }, + { (char*) "Asia/Ashkhabad" , 0x024139 }, + { (char*) "Asia/Atyrau" , 0x0242BC }, + { (char*) "Asia/Baghdad" , 0x024545 }, + { (char*) "Asia/Bahrain" , 0x0247C7 }, + { (char*) "Asia/Baku" , 0x024880 }, + { (char*) "Asia/Bangkok" , 0x024B74 }, + { (char*) "Asia/Barnaul" , 0x024C18 }, + { (char*) "Asia/Beirut" , 0x024F23 }, + { (char*) "Asia/Bishkek" , 0x02520B }, + { (char*) "Asia/Brunei" , 0x025481 }, + { (char*) "Asia/Calcutta" , 0x025527 }, + { (char*) "Asia/Chita" , 0x02560F }, + { (char*) "Asia/Choibalsan" , 0x02591D }, + { (char*) "Asia/Chongqing" , 0x025B7B }, + { (char*) "Asia/Chungking" , 0x025D10 }, + { (char*) "Asia/Colombo" , 0x025EA5 }, + { (char*) "Asia/Dacca" , 0x025FA8 }, + { (char*) "Asia/Damascus" , 0x02609B }, + { (char*) "Asia/Dhaka" , 0x026579 }, + { (char*) "Asia/Dili" , 0x02666C }, + { (char*) "Asia/Dubai" , 0x026722 }, + { (char*) "Asia/Dushanbe" , 0x0267B3 }, + { (char*) "Asia/Famagusta" , 0x02692D }, + { (char*) "Asia/Gaza" , 0x026CF4 }, + { (char*) "Asia/Harbin" , 0x027890 }, + { (char*) "Asia/Hebron" , 0x027A25 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x0285D2 }, + { (char*) "Asia/Hong_Kong" , 0x0286CA }, + { (char*) "Asia/Hovd" , 0x0289DD }, + { (char*) "Asia/Irkutsk" , 0x028C51 }, + { (char*) "Asia/Istanbul" , 0x028F6F }, + { (char*) "Asia/Jakarta" , 0x02942B }, + { (char*) "Asia/Jayapura" , 0x02953C }, + { (char*) "Asia/Jerusalem" , 0x029629 }, + { (char*) "Asia/Kabul" , 0x029A67 }, + { (char*) "Asia/Kamchatka" , 0x029B12 }, + { (char*) "Asia/Karachi" , 0x029E07 }, + { (char*) "Asia/Kashgar" , 0x029F1D }, + { (char*) "Asia/Kathmandu" , 0x029FAE }, + { (char*) "Asia/Katmandu" , 0x02A05B }, + { (char*) "Asia/Khandyga" , 0x02A108 }, + { (char*) "Asia/Kolkata" , 0x02A439 }, + { (char*) "Asia/Krasnoyarsk" , 0x02A521 }, + { (char*) "Asia/Kuala_Lumpur" , 0x02A82B }, + { (char*) "Asia/Kuching" , 0x02A94B }, + { (char*) "Asia/Kuwait" , 0x02AAA5 }, + { (char*) "Asia/Macao" , 0x02AB36 }, + { (char*) "Asia/Macau" , 0x02AE59 }, + { (char*) "Asia/Magadan" , 0x02B17C }, + { (char*) "Asia/Makassar" , 0x02B487 }, + { (char*) "Asia/Manila" , 0x02B59A }, + { (char*) "Asia/Muscat" , 0x02B6B8 }, + { (char*) "Asia/Nicosia" , 0x02B749 }, + { (char*) "Asia/Novokuznetsk" , 0x02B9B8 }, + { (char*) "Asia/Novosibirsk" , 0x02BCAB }, + { (char*) "Asia/Omsk" , 0x02BFBC }, + { (char*) "Asia/Oral" , 0x02C2BA }, + { (char*) "Asia/Phnom_Penh" , 0x02C546 }, + { (char*) "Asia/Pontianak" , 0x02C61A }, + { (char*) "Asia/Pyongyang" , 0x02C733 }, + { (char*) "Asia/Qatar" , 0x02C7F6 }, + { (char*) "Asia/Qostanay" , 0x02C89A }, + { (char*) "Asia/Qyzylorda" , 0x02CB30 }, + { (char*) "Asia/Rangoon" , 0x02CDC9 }, + { (char*) "Asia/Riyadh" , 0x02CE90 }, + { (char*) "Asia/Saigon" , 0x02CF21 }, + { (char*) "Asia/Sakhalin" , 0x02D019 }, + { (char*) "Asia/Samarkand" , 0x02D330 }, + { (char*) "Asia/Seoul" , 0x02D4BB }, + { (char*) "Asia/Shanghai" , 0x02D666 }, + { (char*) "Asia/Singapore" , 0x02D807 }, + { (char*) "Asia/Srednekolymsk" , 0x02D913 }, + { (char*) "Asia/Taipei" , 0x02DC23 }, + { (char*) "Asia/Tashkent" , 0x02DE2E }, + { (char*) "Asia/Tbilisi" , 0x02DFB9 }, + { (char*) "Asia/Tehran" , 0x02E23A }, + { (char*) "Asia/Tel_Aviv" , 0x02E572 }, + { (char*) "Asia/Thimbu" , 0x02E9B0 }, + { (char*) "Asia/Thimphu" , 0x02EA56 }, + { (char*) "Asia/Tokyo" , 0x02EAFC }, + { (char*) "Asia/Tomsk" , 0x02EBDD }, + { (char*) "Asia/Ujung_Pandang" , 0x02EEE8 }, + { (char*) "Asia/Ulaanbaatar" , 0x02EFB2 }, + { (char*) "Asia/Ulan_Bator" , 0x02F220 }, + { (char*) "Asia/Urumqi" , 0x02F47E }, + { (char*) "Asia/Ust-Nera" , 0x02F51C }, + { (char*) "Asia/Vientiane" , 0x02F83F }, + { (char*) "Asia/Vladivostok" , 0x02F925 }, + { (char*) "Asia/Yakutsk" , 0x02FC2A }, + { (char*) "Asia/Yangon" , 0x02FF2E }, + { (char*) "Asia/Yekaterinburg" , 0x02FFF5 }, + { (char*) "Asia/Yerevan" , 0x030307 }, + { (char*) "Atlantic/Azores" , 0x0305D7 }, + { (char*) "Atlantic/Bermuda" , 0x030B62 }, + { (char*) "Atlantic/Canary" , 0x030F6E }, + { (char*) "Atlantic/Cape_Verde" , 0x031166 }, + { (char*) "Atlantic/Faeroe" , 0x031221 }, + { (char*) "Atlantic/Faroe" , 0x0313E6 }, + { (char*) "Atlantic/Jan_Mayen" , 0x0315AB }, + { (char*) "Atlantic/Madeira" , 0x031878 }, + { (char*) "Atlantic/Reykjavik" , 0x031DEF }, + { (char*) "Atlantic/South_Georgia" , 0x0320EC }, + { (char*) "Atlantic/St_Helena" , 0x03217C }, + { (char*) "Atlantic/Stanley" , 0x03221D }, + { (char*) "Australia/ACT" , 0x03253E }, + { (char*) "Australia/Adelaide" , 0x0328D2 }, + { (char*) "Australia/Brisbane" , 0x032C86 }, + { (char*) "Australia/Broken_Hill" , 0x032DCA }, + { (char*) "Australia/Canberra" , 0x03319F }, + { (char*) "Australia/Currie" , 0x033533 }, + { (char*) "Australia/Darwin" , 0x03392A }, + { (char*) "Australia/Eucla" , 0x033A32 }, + { (char*) "Australia/Hobart" , 0x033B91 }, + { (char*) "Australia/LHI" , 0x033F90 }, + { (char*) "Australia/Lindeman" , 0x034250 }, + { (char*) "Australia/Lord_Howe" , 0x0343C0 }, + { (char*) "Australia/Melbourne" , 0x034690 }, + { (char*) "Australia/North" , 0x034A2C }, + { (char*) "Australia/NSW" , 0x034B22 }, + { (char*) "Australia/Perth" , 0x034EB6 }, + { (char*) "Australia/Queensland" , 0x035012 }, + { (char*) "Australia/South" , 0x03513F }, + { (char*) "Australia/Sydney" , 0x0354E4 }, + { (char*) "Australia/Tasmania" , 0x035894 }, + { (char*) "Australia/Victoria" , 0x035C8B }, + { (char*) "Australia/West" , 0x03601F }, + { (char*) "Australia/Yancowinna" , 0x03615D }, + { (char*) "Brazil/Acre" , 0x036516 }, + { (char*) "Brazil/DeNoronha" , 0x0366C4 }, + { (char*) "Brazil/East" , 0x0368B4 }, + { (char*) "Brazil/West" , 0x036C78 }, + { (char*) "Canada/Atlantic" , 0x036E20 }, + { (char*) "Canada/Central" , 0x0374B4 }, + { (char*) "Canada/Eastern" , 0x0379CE }, + { (char*) "Canada/Mountain" , 0x03808F }, + { (char*) "Canada/Newfoundland" , 0x038465 }, + { (char*) "Canada/Pacific" , 0x038BC7 }, + { (char*) "Canada/Saskatchewan" , 0x039105 }, + { (char*) "Canada/Yukon" , 0x03938F }, + { (char*) "CET" , 0x0397A0 }, + { (char*) "Chile/Continental" , 0x039BFB }, + { (char*) "Chile/EasterIsland" , 0x03A151 }, + { (char*) "CST6CDT" , 0x03A5F3 }, + { (char*) "Cuba" , 0x03ACD9 }, + { (char*) "EET" , 0x03B142 }, + { (char*) "Egypt" , 0x03B3F8 }, + { (char*) "Eire" , 0x03B921 }, + { (char*) "EST" , 0x03BF05 }, + { (char*) "EST5EDT" , 0x03BFA6 }, + { (char*) "Etc/GMT" , 0x03C682 }, + { (char*) "Etc/GMT+0" , 0x03C6FD }, + { (char*) "Etc/GMT+1" , 0x03C778 }, + { (char*) "Etc/GMT+10" , 0x03C7F5 }, + { (char*) "Etc/GMT+11" , 0x03C873 }, + { (char*) "Etc/GMT+12" , 0x03C8F1 }, + { (char*) "Etc/GMT+2" , 0x03C96F }, + { (char*) "Etc/GMT+3" , 0x03C9EC }, + { (char*) "Etc/GMT+4" , 0x03CA69 }, + { (char*) "Etc/GMT+5" , 0x03CAE6 }, + { (char*) "Etc/GMT+6" , 0x03CB63 }, + { (char*) "Etc/GMT+7" , 0x03CBE0 }, + { (char*) "Etc/GMT+8" , 0x03CC5D }, + { (char*) "Etc/GMT+9" , 0x03CCDA }, + { (char*) "Etc/GMT-0" , 0x03CD57 }, + { (char*) "Etc/GMT-1" , 0x03CDD2 }, + { (char*) "Etc/GMT-10" , 0x03CE50 }, + { (char*) "Etc/GMT-11" , 0x03CECF }, + { (char*) "Etc/GMT-12" , 0x03CF4E }, + { (char*) "Etc/GMT-13" , 0x03CFCD }, + { (char*) "Etc/GMT-14" , 0x03D04C }, + { (char*) "Etc/GMT-2" , 0x03D0CB }, + { (char*) "Etc/GMT-3" , 0x03D149 }, + { (char*) "Etc/GMT-4" , 0x03D1C7 }, + { (char*) "Etc/GMT-5" , 0x03D245 }, + { (char*) "Etc/GMT-6" , 0x03D2C3 }, + { (char*) "Etc/GMT-7" , 0x03D341 }, + { (char*) "Etc/GMT-8" , 0x03D3BF }, + { (char*) "Etc/GMT-9" , 0x03D43D }, + { (char*) "Etc/GMT0" , 0x03D4BB }, + { (char*) "Etc/Greenwich" , 0x03D536 }, + { (char*) "Etc/UCT" , 0x03D5B1 }, + { (char*) "Etc/Universal" , 0x03D62C }, + { (char*) "Etc/UTC" , 0x03D6A7 }, + { (char*) "Etc/Zulu" , 0x03D722 }, + { (char*) "Europe/Amsterdam" , 0x03D79D }, + { (char*) "Europe/Andorra" , 0x03DBD8 }, + { (char*) "Europe/Astrakhan" , 0x03DD69 }, + { (char*) "Europe/Athens" , 0x03E05D }, + { (char*) "Europe/Belfast" , 0x03E313 }, + { (char*) "Europe/Belgrade" , 0x03E95E }, + { (char*) "Europe/Berlin" , 0x03EB48 }, + { (char*) "Europe/Bratislava" , 0x03EE24 }, + { (char*) "Europe/Brussels" , 0x03F103 }, + { (char*) "Europe/Bucharest" , 0x03F55E }, + { (char*) "Europe/Budapest" , 0x03F7FF }, + { (char*) "Europe/Busingen" , 0x03FB09 }, + { (char*) "Europe/Chisinau" , 0x03FD0E }, + { (char*) "Europe/Copenhagen" , 0x04000D }, + { (char*) "Europe/Dublin" , 0x040288 }, + { (char*) "Europe/Gibraltar" , 0x04086C }, + { (char*) "Europe/Guernsey" , 0x040D3C }, + { (char*) "Europe/Helsinki" , 0x041393 }, + { (char*) "Europe/Isle_of_Man" , 0x041580 }, + { (char*) "Europe/Istanbul" , 0x041BCB }, + { (char*) "Europe/Jersey" , 0x042087 }, + { (char*) "Europe/Kaliningrad" , 0x0426DE }, + { (char*) "Europe/Kiev" , 0x042A86 }, + { (char*) "Europe/Kirov" , 0x042CC0 }, + { (char*) "Europe/Kyiv" , 0x042FB9 }, + { (char*) "Europe/Lisbon" , 0x043202 }, + { (char*) "Europe/Ljubljana" , 0x0437D8 }, + { (char*) "Europe/London" , 0x0439C2 }, + { (char*) "Europe/Luxembourg" , 0x04400D }, + { (char*) "Europe/Madrid" , 0x044458 }, + { (char*) "Europe/Malta" , 0x0447F5 }, + { (char*) "Europe/Mariehamn" , 0x044BA1 }, + { (char*) "Europe/Minsk" , 0x044D8E }, + { (char*) "Europe/Monaco" , 0x0450C2 }, + { (char*) "Europe/Moscow" , 0x045528 }, + { (char*) "Europe/Nicosia" , 0x0458D4 }, + { (char*) "Europe/Oslo" , 0x045B35 }, + { (char*) "Europe/Paris" , 0x045DE5 }, + { (char*) "Europe/Podgorica" , 0x046242 }, + { (char*) "Europe/Prague" , 0x04642C }, + { (char*) "Europe/Riga" , 0x04670B }, + { (char*) "Europe/Rome" , 0x0469CD }, + { (char*) "Europe/Samara" , 0x046D8C }, + { (char*) "Europe/San_Marino" , 0x04708D }, + { (char*) "Europe/Sarajevo" , 0x04744C }, + { (char*) "Europe/Saratov" , 0x047636 }, + { (char*) "Europe/Simferopol" , 0x047928 }, + { (char*) "Europe/Skopje" , 0x047C9B }, + { (char*) "Europe/Sofia" , 0x047E85 }, + { (char*) "Europe/Stockholm" , 0x0480E1 }, + { (char*) "Europe/Tallinn" , 0x0482DE }, + { (char*) "Europe/Tirane" , 0x04858D }, + { (char*) "Europe/Tiraspol" , 0x0487F5 }, + { (char*) "Europe/Ulyanovsk" , 0x048AF4 }, + { (char*) "Europe/Uzhgorod" , 0x048E0A }, + { (char*) "Europe/Vaduz" , 0x049044 }, + { (char*) "Europe/Vatican" , 0x04922E }, + { (char*) "Europe/Vienna" , 0x0495ED }, + { (char*) "Europe/Vilnius" , 0x04988B }, + { (char*) "Europe/Volgograd" , 0x049B3B }, + { (char*) "Europe/Warsaw" , 0x049E4A }, + { (char*) "Europe/Zagreb" , 0x04A1F1 }, + { (char*) "Europe/Zaporozhye" , 0x04A3DB }, + { (char*) "Europe/Zurich" , 0x04A615 }, + { (char*) "Factory" , 0x04A812 }, + { (char*) "GB" , 0x04A88F }, + { (char*) "GB-Eire" , 0x04AEDA }, + { (char*) "GMT" , 0x04B525 }, + { (char*) "GMT+0" , 0x04B5A0 }, + { (char*) "GMT-0" , 0x04B61B }, + { (char*) "GMT0" , 0x04B696 }, + { (char*) "Greenwich" , 0x04B711 }, + { (char*) "Hongkong" , 0x04B78C }, + { (char*) "HST" , 0x04BA9F }, + { (char*) "Iceland" , 0x04BB88 }, + { (char*) "Indian/Antananarivo" , 0x04BC16 }, + { (char*) "Indian/Chagos" , 0x04BCC2 }, + { (char*) "Indian/Christmas" , 0x04BD66 }, + { (char*) "Indian/Cocos" , 0x04BDF7 }, + { (char*) "Indian/Comoro" , 0x04BE8F }, + { (char*) "Indian/Kerguelen" , 0x04BF1E }, + { (char*) "Indian/Mahe" , 0x04BFAF }, + { (char*) "Indian/Maldives" , 0x04C040 }, + { (char*) "Indian/Mauritius" , 0x04C0E4 }, + { (char*) "Indian/Mayotte" , 0x04C1A3 }, + { (char*) "Indian/Reunion" , 0x04C232 }, + { (char*) "Iran" , 0x04C2C3 }, + { (char*) "Israel" , 0x04C5FB }, + { (char*) "Jamaica" , 0x04CA39 }, + { (char*) "Japan" , 0x04CB98 }, + { (char*) "Kwajalein" , 0x04CC79 }, + { (char*) "Libya" , 0x04CD60 }, + { (char*) "MET" , 0x04CF1B }, + { (char*) "Mexico/BajaNorte" , 0x04D376 }, + { (char*) "Mexico/BajaSur" , 0x04D7B9 }, + { (char*) "Mexico/General" , 0x04DA77 }, + { (char*) "MST" , 0x04DD88 }, + { (char*) "MST7MDT" , 0x04DE84 }, + { (char*) "Navajo" , 0x04E2A2 }, + { (char*) "NZ" , 0x04E6C0 }, + { (char*) "NZ-CHAT" , 0x04EADF }, + { (char*) "Pacific/Apia" , 0x04EE13 }, + { (char*) "Pacific/Auckland" , 0x04EFB6 }, + { (char*) "Pacific/Bougainville" , 0x04F3E8 }, + { (char*) "Pacific/Chatham" , 0x04F4C9 }, + { (char*) "Pacific/Chuuk" , 0x04F80C }, + { (char*) "Pacific/Easter" , 0x04F8EA }, + { (char*) "Pacific/Efate" , 0x04FD99 }, + { (char*) "Pacific/Enderbury" , 0x04FEFB }, + { (char*) "Pacific/Fakaofo" , 0x04FFB3 }, + { (char*) "Pacific/Fiji" , 0x050058 }, + { (char*) "Pacific/Funafuti" , 0x0501F0 }, + { (char*) "Pacific/Galapagos" , 0x050282 }, + { (char*) "Pacific/Gambier" , 0x05034E }, + { (char*) "Pacific/Guadalcanal" , 0x0503ED }, + { (char*) "Pacific/Guam" , 0x05047F }, + { (char*) "Pacific/Honolulu" , 0x0505E9 }, + { (char*) "Pacific/Johnston" , 0x0506D8 }, + { (char*) "Pacific/Kanton" , 0x0507C1 }, + { (char*) "Pacific/Kiritimati" , 0x050888 }, + { (char*) "Pacific/Kosrae" , 0x05094E }, + { (char*) "Pacific/Kwajalein" , 0x050A52 }, + { (char*) "Pacific/Majuro" , 0x050B42 }, + { (char*) "Pacific/Marquesas" , 0x050C40 }, + { (char*) "Pacific/Midway" , 0x050CE8 }, + { (char*) "Pacific/Nauru" , 0x050DAB }, + { (char*) "Pacific/Niue" , 0x050E6E }, + { (char*) "Pacific/Norfolk" , 0x050F14 }, + { (char*) "Pacific/Noumea" , 0x05100D }, + { (char*) "Pacific/Pago_Pago" , 0x0510DF }, + { (char*) "Pacific/Palau" , 0x05117D }, + { (char*) "Pacific/Pitcairn" , 0x05121D }, + { (char*) "Pacific/Pohnpei" , 0x0512C2 }, + { (char*) "Pacific/Ponape" , 0x0513B2 }, + { (char*) "Pacific/Port_Moresby" , 0x051444 }, + { (char*) "Pacific/Rarotonga" , 0x051502 }, + { (char*) "Pacific/Saipan" , 0x0516A4 }, + { (char*) "Pacific/Samoa" , 0x051805 }, + { (char*) "Pacific/Tahiti" , 0x0518A3 }, + { (char*) "Pacific/Tarawa" , 0x051943 }, + { (char*) "Pacific/Tongatapu" , 0x0519E4 }, + { (char*) "Pacific/Truk" , 0x051ADD }, + { (char*) "Pacific/Wake" , 0x051B83 }, + { (char*) "Pacific/Wallis" , 0x051C20 }, + { (char*) "Pacific/Yap" , 0x051CB2 }, + { (char*) "Poland" , 0x051D58 }, + { (char*) "Portugal" , 0x0520FF }, + { (char*) "PRC" , 0x0526C2 }, + { (char*) "PST8PDT" , 0x052857 }, + { (char*) "ROC" , 0x052D71 }, + { (char*) "ROK" , 0x052F7C }, + { (char*) "Singapore" , 0x053127 }, + { (char*) "Turkey" , 0x053233 }, + { (char*) "UCT" , 0x0536EF }, + { (char*) "Universal" , 0x05376A }, + { (char*) "US/Alaska" , 0x0537E5 }, + { (char*) "US/Aleutian" , 0x053BC2 }, + { (char*) "US/Arizona" , 0x053F97 }, + { (char*) "US/Central" , 0x054093 }, + { (char*) "US/East-Indiana" , 0x054779 }, + { (char*) "US/Eastern" , 0x054998 }, + { (char*) "US/Hawaii" , 0x055074 }, + { (char*) "US/Indiana-Starke" , 0x05515D }, + { (char*) "US/Michigan" , 0x055561 }, + { (char*) "US/Mountain" , 0x0558F0 }, + { (char*) "US/Pacific" , 0x055D0E }, + { (char*) "US/Samoa" , 0x056228 }, + { (char*) "UTC" , 0x0562C6 }, + { (char*) "W-SU" , 0x056341 }, + { (char*) "WET" , 0x0566D9 }, + { (char*) "Zulu" , 0x056C9C }, }; -const unsigned char timelib_timezone_db_data_builtin[354224] = { +const unsigned char timelib_timezone_db_data_builtin[355607] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3709,6 +3710,95 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0xFF, +0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, +0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, +0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, +0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, +0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, 0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, +0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, +0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, 0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, +0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x87, 0x40, 0x00, +0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x60, 0x69, 0x40, 0x00, +0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, +0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, +0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x94, 0x40, 0x00, +0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, +0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, +0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, 0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, +0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, +0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, +0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x06, 0xFF, 0xFF, 0xBC, 0x70, +0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, +0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, +0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, +0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, +0x33, 0x0A, 0x00, 0x43, 0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, +0x73, 0x65, 0x6E, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -7899,9 +7989,8 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, -0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, -0x67, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, -0x65, 0x73, +0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, +0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -13146,7 +13235,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -21311,7 +21400,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -24240,7 +24329,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #else -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x0000A0 }, { (char*) "Africa/Addis_Ababa" , 0x0004D0 }, @@ -24340,508 +24429,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x0114AF }, { (char*) "America/Cordoba" , 0x011571 }, { (char*) "America/Costa_Rica" , 0x0119A3 }, - { (char*) "America/Creston" , 0x011AEB }, - { (char*) "America/Cuiaba" , 0x011BD9 }, - { (char*) "America/Curacao" , 0x01216A }, - { (char*) "America/Danmarkshavn" , 0x012230 }, - { (char*) "America/Dawson" , 0x012510 }, - { (char*) "America/Dawson_Creek" , 0x012B7C }, - { (char*) "America/Denver" , 0x012FC2 }, - { (char*) "America/Detroit" , 0x01397F }, - { (char*) "America/Dominica" , 0x01425A }, - { (char*) "America/Edmonton" , 0x0142FA }, - { (char*) "America/Eirunepe" , 0x014C44 }, - { (char*) "America/El_Salvador" , 0x014EE1 }, - { (char*) "America/Ensenada" , 0x014FCD }, - { (char*) "America/Fort_Nelson" , 0x015973 }, - { (char*) "America/Fort_Wayne" , 0x016253 }, - { (char*) "America/Fortaleza" , 0x0168F1 }, - { (char*) "America/Glace_Bay" , 0x016BE1 }, - { (char*) "America/Godthab" , 0x017498 }, - { (char*) "America/Goose_Bay" , 0x017C05 }, - { (char*) "America/Grand_Turk" , 0x0188BB }, - { (char*) "America/Grenada" , 0x018FF1 }, - { (char*) "America/Guadeloupe" , 0x019091 }, - { (char*) "America/Guatemala" , 0x019131 }, - { (char*) "America/Guayaquil" , 0x019255 }, - { (char*) "America/Guyana" , 0x01935B }, - { (char*) "America/Halifax" , 0x01945F }, - { (char*) "America/Havana" , 0x01A1E9 }, - { (char*) "America/Hermosillo" , 0x01AB65 }, - { (char*) "America/Indiana/Indianapolis" , 0x01ACFB }, - { (char*) "America/Indiana/Knox" , 0x01B3B2 }, - { (char*) "America/Indiana/Marengo" , 0x01BD5F }, - { (char*) "America/Indiana/Petersburg" , 0x01C44C }, - { (char*) "America/Indiana/Tell_City" , 0x01CBEB }, - { (char*) "America/Indiana/Vevay" , 0x01D2AF }, - { (char*) "America/Indiana/Vincennes" , 0x01D86B }, - { (char*) "America/Indiana/Winamac" , 0x01DF41 }, - { (char*) "America/Indianapolis" , 0x01E665 }, - { (char*) "America/Inuvik" , 0x01ED03 }, - { (char*) "America/Iqaluit" , 0x01F53D }, - { (char*) "America/Jamaica" , 0x01FDFC }, - { (char*) "America/Jujuy" , 0x01FFEA }, - { (char*) "America/Juneau" , 0x020400 }, - { (char*) "America/Kentucky/Louisville" , 0x020D51 }, - { (char*) "America/Kentucky/Monticello" , 0x02185F }, - { (char*) "America/Knox_IN" , 0x0221BF }, - { (char*) "America/Kralendijk" , 0x022B57 }, - { (char*) "America/La_Paz" , 0x022C59 }, - { (char*) "America/Lima" , 0x022D3F }, - { (char*) "America/Los_Angeles" , 0x022ED3 }, - { (char*) "America/Louisville" , 0x023A0A }, - { (char*) "America/Lower_Princes" , 0x0244FA }, - { (char*) "America/Maceio" , 0x0245FC }, - { (char*) "America/Managua" , 0x0248F2 }, - { (char*) "America/Manaus" , 0x024AAC }, - { (char*) "America/Marigot" , 0x024D15 }, - { (char*) "America/Martinique" , 0x024E17 }, - { (char*) "America/Matamoros" , 0x024F0B }, - { (char*) "America/Mazatlan" , 0x0254CD }, - { (char*) "America/Mendoza" , 0x02592F }, - { (char*) "America/Menominee" , 0x025D61 }, - { (char*) "America/Merida" , 0x02666E }, - { (char*) "America/Metlakatla" , 0x026A77 }, - { (char*) "America/Mexico_City" , 0x027029 }, - { (char*) "America/Miquelon" , 0x027509 }, - { (char*) "America/Moncton" , 0x027B89 }, - { (char*) "America/Monterrey" , 0x0287FF }, - { (char*) "America/Montevideo" , 0x028C9B }, - { (char*) "America/Montreal" , 0x02927F }, - { (char*) "America/Montserrat" , 0x02A031 }, - { (char*) "America/Nassau" , 0x02A0D1 }, - { (char*) "America/New_York" , 0x02AA31 }, - { (char*) "America/Nipigon" , 0x02B831 }, - { (char*) "America/Nome" , 0x02C5E3 }, - { (char*) "America/Noronha" , 0x02CF3B }, - { (char*) "America/North_Dakota/Beulah" , 0x02D215 }, - { (char*) "America/North_Dakota/Center" , 0x02DB92 }, - { (char*) "America/North_Dakota/New_Salem" , 0x02E50F }, - { (char*) "America/Nuuk" , 0x02EE92 }, - { (char*) "America/Ojinaga" , 0x02F610 }, - { (char*) "America/Panama" , 0x02FC2C }, - { (char*) "America/Pangnirtung" , 0x02FCEE }, - { (char*) "America/Paramaribo" , 0x030594 }, - { (char*) "America/Phoenix" , 0x030698 }, - { (char*) "America/Port-au-Prince" , 0x030824 }, - { (char*) "America/Port_of_Spain" , 0x030DCA }, - { (char*) "America/Porto_Acre" , 0x030E6A }, - { (char*) "America/Porto_Velho" , 0x0310DC }, - { (char*) "America/Puerto_Rico" , 0x031322 }, - { (char*) "America/Punta_Arenas" , 0x031424 }, - { (char*) "America/Rainy_River" , 0x031BB2 }, - { (char*) "America/Rankin_Inlet" , 0x0326F2 }, - { (char*) "America/Recife" , 0x032F26 }, - { (char*) "America/Regina" , 0x0331FA }, - { (char*) "America/Resolute" , 0x0335EF }, - { (char*) "America/Rio_Branco" , 0x033E24 }, - { (char*) "America/Rosario" , 0x03409A }, - { (char*) "America/Santa_Isabel" , 0x0344CC }, - { (char*) "America/Santarem" , 0x034E72 }, - { (char*) "America/Santiago" , 0x0350D5 }, - { (char*) "America/Santo_Domingo" , 0x035AC1 }, - { (char*) "America/Sao_Paulo" , 0x035C97 }, - { (char*) "America/Scoresbysund" , 0x03626F }, - { (char*) "America/Shiprock" , 0x036A27 }, - { (char*) "America/Sitka" , 0x0373CF }, - { (char*) "America/St_Barthelemy" , 0x037D07 }, - { (char*) "America/St_Johns" , 0x037E09 }, - { (char*) "America/St_Kitts" , 0x038C77 }, - { (char*) "America/St_Lucia" , 0x038D17 }, - { (char*) "America/St_Thomas" , 0x038DD9 }, - { (char*) "America/St_Vincent" , 0x038E79 }, - { (char*) "America/Swift_Current" , 0x038F3B }, - { (char*) "America/Tegucigalpa" , 0x039189 }, - { (char*) "America/Thule" , 0x039291 }, - { (char*) "America/Thunder_Bay" , 0x039889 }, - { (char*) "America/Tijuana" , 0x03A63B }, - { (char*) "America/Toronto" , 0x03AFF0 }, - { (char*) "America/Tortola" , 0x03BDC0 }, - { (char*) "America/Vancouver" , 0x03BE60 }, - { (char*) "America/Virgin" , 0x03C9D1 }, - { (char*) "America/Whitehorse" , 0x03CAD3 }, - { (char*) "America/Winnipeg" , 0x03D13F }, - { (char*) "America/Yakutat" , 0x03DC9C }, - { (char*) "America/Yellowknife" , 0x03E5B9 }, - { (char*) "Antarctica/Casey" , 0x03EEE1 }, - { (char*) "Antarctica/Davis" , 0x03F099 }, - { (char*) "Antarctica/DumontDUrville" , 0x03F1C5 }, - { (char*) "Antarctica/Macquarie" , 0x03F295 }, - { (char*) "Antarctica/Mawson" , 0x03FB85 }, - { (char*) "Antarctica/McMurdo" , 0x03FC50 }, - { (char*) "Antarctica/Palmer" , 0x04044B }, - { (char*) "Antarctica/Rothera" , 0x0409D9 }, - { (char*) "Antarctica/South_Pole" , 0x040A82 }, - { (char*) "Antarctica/Syowa" , 0x041413 }, - { (char*) "Antarctica/Troll" , 0x0414BB }, - { (char*) "Antarctica/Vostok" , 0x041948 }, - { (char*) "Arctic/Longyearbyen" , 0x041A2F }, - { (char*) "Asia/Aden" , 0x042335 }, - { (char*) "Asia/Almaty" , 0x0423D8 }, - { (char*) "Asia/Amman" , 0x0427CD }, - { (char*) "Asia/Anadyr" , 0x042D72 }, - { (char*) "Asia/Aqtau" , 0x043227 }, - { (char*) "Asia/Aqtobe" , 0x043611 }, - { (char*) "Asia/Ashgabat" , 0x043A0F }, - { (char*) "Asia/Ashkhabad" , 0x043C78 }, - { (char*) "Asia/Atyrau" , 0x043EE1 }, - { (char*) "Asia/Baghdad" , 0x0442D3 }, - { (char*) "Asia/Bahrain" , 0x0446A8 }, - { (char*) "Asia/Baku" , 0x044793 }, - { (char*) "Asia/Bangkok" , 0x044C5C }, - { (char*) "Asia/Barnaul" , 0x044D21 }, - { (char*) "Asia/Beirut" , 0x0451F2 }, - { (char*) "Asia/Bishkek" , 0x045A68 }, - { (char*) "Asia/Brunei" , 0x045E3D }, - { (char*) "Asia/Calcutta" , 0x045F06 }, - { (char*) "Asia/Chita" , 0x04602F }, - { (char*) "Asia/Choibalsan" , 0x046506 }, - { (char*) "Asia/Chongqing" , 0x04687F }, - { (char*) "Asia/Chungking" , 0x046ABC }, - { (char*) "Asia/Colombo" , 0x046CF9 }, - { (char*) "Asia/Dacca" , 0x046E6B }, - { (char*) "Asia/Damascus" , 0x046FBA }, - { (char*) "Asia/Dhaka" , 0x047717 }, - { (char*) "Asia/Dili" , 0x047866 }, - { (char*) "Asia/Dubai" , 0x047973 }, - { (char*) "Asia/Dushanbe" , 0x047A16 }, - { (char*) "Asia/Famagusta" , 0x047C63 }, - { (char*) "Asia/Gaza" , 0x04846A }, - { (char*) "Asia/Harbin" , 0x049384 }, - { (char*) "Asia/Hebron" , 0x0495C1 }, - { (char*) "Asia/Ho_Chi_Minh" , 0x04A4F6 }, - { (char*) "Asia/Hong_Kong" , 0x04A653 }, - { (char*) "Asia/Hovd" , 0x04AB30 }, - { (char*) "Asia/Irkutsk" , 0x04AEBF }, - { (char*) "Asia/Istanbul" , 0x04B3B2 }, - { (char*) "Asia/Jakarta" , 0x04BB4B }, - { (char*) "Asia/Jayapura" , 0x04BCE3 }, - { (char*) "Asia/Jerusalem" , 0x04BE02 }, - { (char*) "Asia/Kabul" , 0x04C762 }, - { (char*) "Asia/Kamchatka" , 0x04C830 }, - { (char*) "Asia/Karachi" , 0x04CCCE }, - { (char*) "Asia/Kashgar" , 0x04CE55 }, - { (char*) "Asia/Kathmandu" , 0x04CEF8 }, - { (char*) "Asia/Katmandu" , 0x04CFCA }, - { (char*) "Asia/Khandyga" , 0x04D09C }, - { (char*) "Asia/Kolkata" , 0x04D5AF }, - { (char*) "Asia/Krasnoyarsk" , 0x04D6D8 }, - { (char*) "Asia/Kuala_Lumpur" , 0x04DBA6 }, - { (char*) "Asia/Kuching" , 0x04DD57 }, - { (char*) "Asia/Kuwait" , 0x04DF46 }, - { (char*) "Asia/Macao" , 0x04DFE9 }, - { (char*) "Asia/Macau" , 0x04E4C0 }, - { (char*) "Asia/Magadan" , 0x04E997 }, - { (char*) "Asia/Makassar" , 0x04EE6B }, - { (char*) "Asia/Manila" , 0x04EFBE }, - { (char*) "Asia/Muscat" , 0x04F170 }, - { (char*) "Asia/Nicosia" , 0x04F213 }, - { (char*) "Asia/Novokuznetsk" , 0x04F9FF }, - { (char*) "Asia/Novosibirsk" , 0x04FE9B }, - { (char*) "Asia/Omsk" , 0x050372 }, - { (char*) "Asia/Oral" , 0x050834 }, - { (char*) "Asia/Phnom_Penh" , 0x050C2E }, - { (char*) "Asia/Pontianak" , 0x050D53 }, - { (char*) "Asia/Pyongyang" , 0x050ED6 }, - { (char*) "Asia/Qatar" , 0x050FCF }, - { (char*) "Asia/Qostanay" , 0x051094 }, - { (char*) "Asia/Qyzylorda" , 0x0514BB }, - { (char*) "Asia/Rangoon" , 0x0518D7 }, - { (char*) "Asia/Riyadh" , 0x0519E1 }, - { (char*) "Asia/Saigon" , 0x051A84 }, - { (char*) "Asia/Sakhalin" , 0x051BE1 }, - { (char*) "Asia/Samarkand" , 0x0520A9 }, - { (char*) "Asia/Seoul" , 0x0522F9 }, - { (char*) "Asia/Shanghai" , 0x05256E }, - { (char*) "Asia/Singapore" , 0x0527B7 }, - { (char*) "Asia/Srednekolymsk" , 0x052954 }, - { (char*) "Asia/Taipei" , 0x052E28 }, - { (char*) "Asia/Tashkent" , 0x05312D }, - { (char*) "Asia/Tbilisi" , 0x05338B }, - { (char*) "Asia/Tehran" , 0x053794 }, - { (char*) "Asia/Tel_Aviv" , 0x053C80 }, - { (char*) "Asia/Thimbu" , 0x0545E0 }, - { (char*) "Asia/Thimphu" , 0x0546A9 }, - { (char*) "Asia/Tokyo" , 0x054772 }, - { (char*) "Asia/Tomsk" , 0x0548B3 }, - { (char*) "Asia/Ujung_Pandang" , 0x054D84 }, - { (char*) "Asia/Ulaanbaatar" , 0x054E8E }, - { (char*) "Asia/Ulan_Bator" , 0x055217 }, - { (char*) "Asia/Urumqi" , 0x055590 }, - { (char*) "Asia/Ust-Nera" , 0x055640 }, - { (char*) "Asia/Vientiane" , 0x055B36 }, - { (char*) "Asia/Vladivostok" , 0x055C77 }, - { (char*) "Asia/Yakutsk" , 0x056140 }, - { (char*) "Asia/Yangon" , 0x056608 }, - { (char*) "Asia/Yekaterinburg" , 0x056712 }, - { (char*) "Asia/Yerevan" , 0x056BF9 }, - { (char*) "Atlantic/Azores" , 0x057076 }, - { (char*) "Atlantic/Bermuda" , 0x057DFA }, - { (char*) "Atlantic/Canary" , 0x058762 }, - { (char*) "Atlantic/Cape_Verde" , 0x058EE5 }, - { (char*) "Atlantic/Faeroe" , 0x058FF1 }, - { (char*) "Atlantic/Faroe" , 0x059714 }, - { (char*) "Atlantic/Jan_Mayen" , 0x059E37 }, - { (char*) "Atlantic/Madeira" , 0x05A73D }, - { (char*) "Atlantic/Reykjavik" , 0x05B489 }, - { (char*) "Atlantic/South_Georgia" , 0x05B91F }, - { (char*) "Atlantic/St_Helena" , 0x05B9C1 }, - { (char*) "Atlantic/Stanley" , 0x05BA83 }, - { (char*) "Australia/ACT" , 0x05BF3F }, - { (char*) "Australia/Adelaide" , 0x05C7D9 }, - { (char*) "Australia/Brisbane" , 0x05D094 }, - { (char*) "Australia/Broken_Hill" , 0x05D25A }, - { (char*) "Australia/Canberra" , 0x05DB37 }, - { (char*) "Australia/Currie" , 0x05E3D1 }, - { (char*) "Australia/Darwin" , 0x05ED13 }, - { (char*) "Australia/Eucla" , 0x05EE76 }, - { (char*) "Australia/Hobart" , 0x05F063 }, - { (char*) "Australia/LHI" , 0x05F9AD }, - { (char*) "Australia/Lindeman" , 0x0600EF }, - { (char*) "Australia/Lord_Howe" , 0x0602F5 }, - { (char*) "Australia/Melbourne" , 0x060A47 }, - { (char*) "Australia/North" , 0x0612E9 }, - { (char*) "Australia/NSW" , 0x06143A }, - { (char*) "Australia/Perth" , 0x061CD4 }, - { (char*) "Australia/Queensland" , 0x061EBC }, - { (char*) "Australia/South" , 0x06206B }, - { (char*) "Australia/Sydney" , 0x062917 }, - { (char*) "Australia/Tasmania" , 0x0631CD }, - { (char*) "Australia/Victoria" , 0x063B0F }, - { (char*) "Australia/West" , 0x0643A9 }, - { (char*) "Australia/Yancowinna" , 0x064573 }, - { (char*) "Brazil/Acre" , 0x064E34 }, - { (char*) "Brazil/DeNoronha" , 0x0650A6 }, - { (char*) "Brazil/East" , 0x065370 }, - { (char*) "Brazil/West" , 0x065912 }, - { (char*) "Canada/Atlantic" , 0x065B6C }, - { (char*) "Canada/Central" , 0x0668D8 }, - { (char*) "Canada/Eastern" , 0x067418 }, - { (char*) "Canada/Mountain" , 0x0681CA }, - { (char*) "Canada/Newfoundland" , 0x068AF2 }, - { (char*) "Canada/Pacific" , 0x069945 }, - { (char*) "Canada/Saskatchewan" , 0x06A49D }, - { (char*) "Canada/Yukon" , 0x06A87D }, - { (char*) "CET" , 0x06AED7 }, - { (char*) "Chile/Continental" , 0x06BA58 }, - { (char*) "Chile/EasterIsland" , 0x06C437 }, - { (char*) "CST6CDT" , 0x06CCEE }, - { (char*) "Cuba" , 0x06DB02 }, - { (char*) "EET" , 0x06E47E }, - { (char*) "Egypt" , 0x06ED60 }, - { (char*) "Eire" , 0x06F6CB }, - { (char*) "EST" , 0x07047B }, - { (char*) "EST5EDT" , 0x07053D }, - { (char*) "Etc/GMT" , 0x071329 }, - { (char*) "Etc/GMT+0" , 0x0713A7 }, - { (char*) "Etc/GMT+1" , 0x071425 }, - { (char*) "Etc/GMT+10" , 0x0714A5 }, - { (char*) "Etc/GMT+11" , 0x071526 }, - { (char*) "Etc/GMT+12" , 0x0715A7 }, - { (char*) "Etc/GMT+2" , 0x071628 }, - { (char*) "Etc/GMT+3" , 0x0716A8 }, - { (char*) "Etc/GMT+4" , 0x071728 }, - { (char*) "Etc/GMT+5" , 0x0717A8 }, - { (char*) "Etc/GMT+6" , 0x071828 }, - { (char*) "Etc/GMT+7" , 0x0718A8 }, - { (char*) "Etc/GMT+8" , 0x071928 }, - { (char*) "Etc/GMT+9" , 0x0719A8 }, - { (char*) "Etc/GMT-0" , 0x071A28 }, - { (char*) "Etc/GMT-1" , 0x071AA6 }, - { (char*) "Etc/GMT-10" , 0x071B27 }, - { (char*) "Etc/GMT-11" , 0x071BA9 }, - { (char*) "Etc/GMT-12" , 0x071C2B }, - { (char*) "Etc/GMT-13" , 0x071CAD }, - { (char*) "Etc/GMT-14" , 0x071D2F }, - { (char*) "Etc/GMT-2" , 0x071DB1 }, - { (char*) "Etc/GMT-3" , 0x071E32 }, - { (char*) "Etc/GMT-4" , 0x071EB3 }, - { (char*) "Etc/GMT-5" , 0x071F34 }, - { (char*) "Etc/GMT-6" , 0x071FB5 }, - { (char*) "Etc/GMT-7" , 0x072036 }, - { (char*) "Etc/GMT-8" , 0x0720B7 }, - { (char*) "Etc/GMT-9" , 0x072138 }, - { (char*) "Etc/GMT0" , 0x0721B9 }, - { (char*) "Etc/Greenwich" , 0x072237 }, - { (char*) "Etc/UCT" , 0x0722B5 }, - { (char*) "Etc/Universal" , 0x072333 }, - { (char*) "Etc/UTC" , 0x0723B1 }, - { (char*) "Etc/Zulu" , 0x07242F }, - { (char*) "Europe/Amsterdam" , 0x0724AD }, - { (char*) "Europe/Andorra" , 0x073017 }, - { (char*) "Europe/Astrakhan" , 0x0736F1 }, - { (char*) "Europe/Athens" , 0x073B8E }, - { (char*) "Europe/Belfast" , 0x074470 }, - { (char*) "Europe/Belgrade" , 0x0752CC }, - { (char*) "Europe/Berlin" , 0x075A58 }, - { (char*) "Europe/Bratislava" , 0x07636D }, - { (char*) "Europe/Brussels" , 0x076C76 }, - { (char*) "Europe/Bucharest" , 0x0777F7 }, - { (char*) "Europe/Budapest" , 0x07808B }, - { (char*) "Europe/Busingen" , 0x0789D7 }, - { (char*) "Europe/Chisinau" , 0x079160 }, - { (char*) "Europe/Copenhagen" , 0x079AC2 }, - { (char*) "Europe/Dublin" , 0x07A327 }, - { (char*) "Europe/Gibraltar" , 0x07B0D7 }, - { (char*) "Europe/Guernsey" , 0x07BCDF }, - { (char*) "Europe/Helsinki" , 0x07CB7F }, - { (char*) "Europe/Isle_of_Man" , 0x07D2F7 }, - { (char*) "Europe/Istanbul" , 0x07E143 }, - { (char*) "Europe/Jersey" , 0x07E8DC }, - { (char*) "Europe/Kaliningrad" , 0x07F77C }, - { (char*) "Europe/Kiev" , 0x07FD71 }, - { (char*) "Europe/Kirov" , 0x0805C5 }, - { (char*) "Europe/Kyiv" , 0x080A80 }, - { (char*) "Europe/Lisbon" , 0x0812E3 }, - { (char*) "Europe/Ljubljana" , 0x0820C9 }, - { (char*) "Europe/London" , 0x082855 }, - { (char*) "Europe/Luxembourg" , 0x0836B1 }, - { (char*) "Europe/Madrid" , 0x08423F }, - { (char*) "Europe/Malta" , 0x084C91 }, - { (char*) "Europe/Mariehamn" , 0x0856D9 }, - { (char*) "Europe/Minsk" , 0x085E51 }, - { (char*) "Europe/Monaco" , 0x086378 }, - { (char*) "Europe/Moscow" , 0x086F04 }, - { (char*) "Europe/Nicosia" , 0x087523 }, - { (char*) "Europe/Oslo" , 0x087D01 }, - { (char*) "Europe/Paris" , 0x0885C1 }, - { (char*) "Europe/Podgorica" , 0x08915F }, - { (char*) "Europe/Prague" , 0x0898EB }, - { (char*) "Europe/Riga" , 0x08A1F4 }, - { (char*) "Europe/Rome" , 0x08AA96 }, - { (char*) "Europe/Samara" , 0x08B4F3 }, - { (char*) "Europe/San_Marino" , 0x08B9C9 }, - { (char*) "Europe/Sarajevo" , 0x08C426 }, - { (char*) "Europe/Saratov" , 0x08CBB2 }, - { (char*) "Europe/Simferopol" , 0x08D05F }, - { (char*) "Europe/Skopje" , 0x08D62E }, - { (char*) "Europe/Sofia" , 0x08DDBA }, - { (char*) "Europe/Stockholm" , 0x08E5E3 }, - { (char*) "Europe/Tallinn" , 0x08ED64 }, - { (char*) "Europe/Tirane" , 0x08F5D4 }, - { (char*) "Europe/Tiraspol" , 0x08FE04 }, - { (char*) "Europe/Ulyanovsk" , 0x090766 }, - { (char*) "Europe/Uzhgorod" , 0x090C69 }, - { (char*) "Europe/Vaduz" , 0x0914BD }, - { (char*) "Europe/Vatican" , 0x091C29 }, - { (char*) "Europe/Vienna" , 0x092686 }, - { (char*) "Europe/Vilnius" , 0x092F2A }, - { (char*) "Europe/Volgograd" , 0x0937A8 }, - { (char*) "Europe/Warsaw" , 0x093C6F }, - { (char*) "Europe/Zagreb" , 0x0946D9 }, - { (char*) "Europe/Zaporozhye" , 0x094E65 }, - { (char*) "Europe/Zurich" , 0x0956B9 }, - { (char*) "Factory" , 0x095E3A }, - { (char*) "GB" , 0x095EBA }, - { (char*) "GB-Eire" , 0x096D16 }, - { (char*) "GMT" , 0x097B72 }, - { (char*) "GMT+0" , 0x097BF0 }, - { (char*) "GMT-0" , 0x097C6E }, - { (char*) "GMT0" , 0x097CEC }, - { (char*) "Greenwich" , 0x097D6A }, - { (char*) "Hongkong" , 0x097DE8 }, - { (char*) "HST" , 0x0982C5 }, - { (char*) "Iceland" , 0x09841A }, - { (char*) "Indian/Antananarivo" , 0x0984BA }, - { (char*) "Indian/Chagos" , 0x0985A1 }, - { (char*) "Indian/Christmas" , 0x098666 }, - { (char*) "Indian/Cocos" , 0x098709 }, - { (char*) "Indian/Comoro" , 0x0987B5 }, - { (char*) "Indian/Kerguelen" , 0x098856 }, - { (char*) "Indian/Mahe" , 0x0988F9 }, - { (char*) "Indian/Maldives" , 0x09899C }, - { (char*) "Indian/Mauritius" , 0x098A61 }, - { (char*) "Indian/Mayotte" , 0x098B50 }, - { (char*) "Indian/Reunion" , 0x098BF1 }, - { (char*) "Iran" , 0x098C94 }, - { (char*) "Israel" , 0x099180 }, - { (char*) "Jamaica" , 0x099AE0 }, - { (char*) "Japan" , 0x099CCE }, - { (char*) "Kwajalein" , 0x099E0F }, - { (char*) "Libya" , 0x099F49 }, - { (char*) "MET" , 0x09A1C6 }, - { (char*) "Mexico/BajaNorte" , 0x09AD47 }, - { (char*) "Mexico/BajaSur" , 0x09B6ED }, - { (char*) "Mexico/General" , 0x09BB1D }, - { (char*) "MST" , 0x09BFEF }, - { (char*) "MST7MDT" , 0x09C163 }, - { (char*) "Navajo" , 0x09CB0B }, - { (char*) "NZ" , 0x09D4B3 }, - { (char*) "NZ-CHAT" , 0x09DE44 }, - { (char*) "Pacific/Apia" , 0x09E656 }, - { (char*) "Pacific/Auckland" , 0x09E8B8 }, - { (char*) "Pacific/Bougainville" , 0x09F25C }, - { (char*) "Pacific/Chatham" , 0x09F372 }, - { (char*) "Pacific/Chuuk" , 0x09FB93 }, - { (char*) "Pacific/Easter" , 0x09FCAD }, - { (char*) "Pacific/Efate" , 0x0A0571 }, - { (char*) "Pacific/Enderbury" , 0x0A0789 }, - { (char*) "Pacific/Fakaofo" , 0x0A0871 }, - { (char*) "Pacific/Fiji" , 0x0A0937 }, - { (char*) "Pacific/Funafuti" , 0x0A0B77 }, - { (char*) "Pacific/Galapagos" , 0x0A0C1B }, - { (char*) "Pacific/Gambier" , 0x0A0D18 }, - { (char*) "Pacific/Guadalcanal" , 0x0A0DC9 }, - { (char*) "Pacific/Guam" , 0x0A0E6D }, - { (char*) "Pacific/Honolulu" , 0x0A1067 }, - { (char*) "Pacific/Johnston" , 0x0A11C2 }, - { (char*) "Pacific/Kanton" , 0x0A1317 }, - { (char*) "Pacific/Kiritimati" , 0x0A140E }, - { (char*) "Pacific/Kosrae" , 0x0A1506 }, - { (char*) "Pacific/Kwajalein" , 0x0A1669 }, - { (char*) "Pacific/Majuro" , 0x0A17AC }, - { (char*) "Pacific/Marquesas" , 0x0A18F8 }, - { (char*) "Pacific/Midway" , 0x0A19B4 }, - { (char*) "Pacific/Nauru" , 0x0A1AA7 }, - { (char*) "Pacific/Niue" , 0x0A1BA1 }, - { (char*) "Pacific/Norfolk" , 0x0A1C6A }, - { (char*) "Pacific/Noumea" , 0x0A1FD8 }, - { (char*) "Pacific/Pago_Pago" , 0x0A2106 }, - { (char*) "Pacific/Palau" , 0x0A21C1 }, - { (char*) "Pacific/Pitcairn" , 0x0A2273 }, - { (char*) "Pacific/Pohnpei" , 0x0A233B }, - { (char*) "Pacific/Ponape" , 0x0A2476 }, - { (char*) "Pacific/Port_Moresby" , 0x0A251A }, - { (char*) "Pacific/Rarotonga" , 0x0A25EA }, - { (char*) "Pacific/Saipan" , 0x0A2843 }, - { (char*) "Pacific/Samoa" , 0x0A2A2F }, - { (char*) "Pacific/Tahiti" , 0x0A2AEA }, - { (char*) "Pacific/Tarawa" , 0x0A2B9C }, - { (char*) "Pacific/Tongatapu" , 0x0A2C4F }, - { (char*) "Pacific/Truk" , 0x0A2DC1 }, - { (char*) "Pacific/Wake" , 0x0A2E79 }, - { (char*) "Pacific/Wallis" , 0x0A2F28 }, - { (char*) "Pacific/Yap" , 0x0A2FCC }, - { (char*) "Poland" , 0x0A3084 }, - { (char*) "Portugal" , 0x0A3AEE }, - { (char*) "PRC" , 0x0A48C1 }, - { (char*) "PST8PDT" , 0x0A4AFE }, - { (char*) "ROC" , 0x0A562E }, - { (char*) "ROK" , 0x0A5933 }, - { (char*) "Singapore" , 0x0A5BA8 }, - { (char*) "Turkey" , 0x0A5D45 }, - { (char*) "UCT" , 0x0A64DE }, - { (char*) "Universal" , 0x0A655C }, - { (char*) "US/Alaska" , 0x0A65DA }, - { (char*) "US/Aleutian" , 0x0A6F29 }, - { (char*) "US/Arizona" , 0x0A7869 }, - { (char*) "US/Central" , 0x0A79DD }, - { (char*) "US/East-Indiana" , 0x0A87F1 }, - { (char*) "US/Eastern" , 0x0A8E8F }, - { (char*) "US/Hawaii" , 0x0A9C7B }, - { (char*) "US/Indiana-Starke" , 0x0A9DD0 }, - { (char*) "US/Michigan" , 0x0AA768 }, - { (char*) "US/Mountain" , 0x0AB02A }, - { (char*) "US/Pacific" , 0x0AB9D2 }, - { (char*) "US/Samoa" , 0x0AC502 }, - { (char*) "UTC" , 0x0AC5BD }, - { (char*) "W-SU" , 0x0AC63B }, - { (char*) "WET" , 0x0ACC46 }, - { (char*) "Zulu" , 0x0ADA19 }, + { (char*) "America/Coyhaique" , 0x011AEB }, + { (char*) "America/Creston" , 0x012351 }, + { (char*) "America/Cuiaba" , 0x01243F }, + { (char*) "America/Curacao" , 0x0129D0 }, + { (char*) "America/Danmarkshavn" , 0x012A96 }, + { (char*) "America/Dawson" , 0x012D76 }, + { (char*) "America/Dawson_Creek" , 0x0133E2 }, + { (char*) "America/Denver" , 0x013828 }, + { (char*) "America/Detroit" , 0x0141E5 }, + { (char*) "America/Dominica" , 0x014AC0 }, + { (char*) "America/Edmonton" , 0x014B60 }, + { (char*) "America/Eirunepe" , 0x0154AA }, + { (char*) "America/El_Salvador" , 0x015747 }, + { (char*) "America/Ensenada" , 0x015833 }, + { (char*) "America/Fort_Nelson" , 0x0161D9 }, + { (char*) "America/Fort_Wayne" , 0x016AB9 }, + { (char*) "America/Fortaleza" , 0x017157 }, + { (char*) "America/Glace_Bay" , 0x017447 }, + { (char*) "America/Godthab" , 0x017CFE }, + { (char*) "America/Goose_Bay" , 0x01846B }, + { (char*) "America/Grand_Turk" , 0x019121 }, + { (char*) "America/Grenada" , 0x019857 }, + { (char*) "America/Guadeloupe" , 0x0198F7 }, + { (char*) "America/Guatemala" , 0x019997 }, + { (char*) "America/Guayaquil" , 0x019ABB }, + { (char*) "America/Guyana" , 0x019BC1 }, + { (char*) "America/Halifax" , 0x019CC5 }, + { (char*) "America/Havana" , 0x01AA4F }, + { (char*) "America/Hermosillo" , 0x01B3CB }, + { (char*) "America/Indiana/Indianapolis" , 0x01B561 }, + { (char*) "America/Indiana/Knox" , 0x01BC18 }, + { (char*) "America/Indiana/Marengo" , 0x01C5C5 }, + { (char*) "America/Indiana/Petersburg" , 0x01CCB2 }, + { (char*) "America/Indiana/Tell_City" , 0x01D451 }, + { (char*) "America/Indiana/Vevay" , 0x01DB15 }, + { (char*) "America/Indiana/Vincennes" , 0x01E0D1 }, + { (char*) "America/Indiana/Winamac" , 0x01E7A7 }, + { (char*) "America/Indianapolis" , 0x01EECB }, + { (char*) "America/Inuvik" , 0x01F569 }, + { (char*) "America/Iqaluit" , 0x01FDA3 }, + { (char*) "America/Jamaica" , 0x020662 }, + { (char*) "America/Jujuy" , 0x020850 }, + { (char*) "America/Juneau" , 0x020C66 }, + { (char*) "America/Kentucky/Louisville" , 0x0215B7 }, + { (char*) "America/Kentucky/Monticello" , 0x0220C5 }, + { (char*) "America/Knox_IN" , 0x022A25 }, + { (char*) "America/Kralendijk" , 0x0233BD }, + { (char*) "America/La_Paz" , 0x0234BF }, + { (char*) "America/Lima" , 0x0235A5 }, + { (char*) "America/Los_Angeles" , 0x023739 }, + { (char*) "America/Louisville" , 0x024270 }, + { (char*) "America/Lower_Princes" , 0x024D60 }, + { (char*) "America/Maceio" , 0x024E62 }, + { (char*) "America/Managua" , 0x025158 }, + { (char*) "America/Manaus" , 0x025312 }, + { (char*) "America/Marigot" , 0x02557B }, + { (char*) "America/Martinique" , 0x02567D }, + { (char*) "America/Matamoros" , 0x025771 }, + { (char*) "America/Mazatlan" , 0x025D33 }, + { (char*) "America/Mendoza" , 0x026195 }, + { (char*) "America/Menominee" , 0x0265C7 }, + { (char*) "America/Merida" , 0x026ED4 }, + { (char*) "America/Metlakatla" , 0x0272DD }, + { (char*) "America/Mexico_City" , 0x02788F }, + { (char*) "America/Miquelon" , 0x027D6F }, + { (char*) "America/Moncton" , 0x0283EF }, + { (char*) "America/Monterrey" , 0x029065 }, + { (char*) "America/Montevideo" , 0x029501 }, + { (char*) "America/Montreal" , 0x029AE5 }, + { (char*) "America/Montserrat" , 0x02A897 }, + { (char*) "America/Nassau" , 0x02A937 }, + { (char*) "America/New_York" , 0x02B297 }, + { (char*) "America/Nipigon" , 0x02C097 }, + { (char*) "America/Nome" , 0x02CE49 }, + { (char*) "America/Noronha" , 0x02D7A1 }, + { (char*) "America/North_Dakota/Beulah" , 0x02DA7B }, + { (char*) "America/North_Dakota/Center" , 0x02E3F8 }, + { (char*) "America/North_Dakota/New_Salem" , 0x02ED75 }, + { (char*) "America/Nuuk" , 0x02F6F8 }, + { (char*) "America/Ojinaga" , 0x02FE76 }, + { (char*) "America/Panama" , 0x030492 }, + { (char*) "America/Pangnirtung" , 0x030554 }, + { (char*) "America/Paramaribo" , 0x030DFA }, + { (char*) "America/Phoenix" , 0x030EFE }, + { (char*) "America/Port-au-Prince" , 0x03108A }, + { (char*) "America/Port_of_Spain" , 0x031630 }, + { (char*) "America/Porto_Acre" , 0x0316D0 }, + { (char*) "America/Porto_Velho" , 0x031942 }, + { (char*) "America/Puerto_Rico" , 0x031B88 }, + { (char*) "America/Punta_Arenas" , 0x031C8A }, + { (char*) "America/Rainy_River" , 0x032415 }, + { (char*) "America/Rankin_Inlet" , 0x032F55 }, + { (char*) "America/Recife" , 0x033789 }, + { (char*) "America/Regina" , 0x033A5D }, + { (char*) "America/Resolute" , 0x033E52 }, + { (char*) "America/Rio_Branco" , 0x034687 }, + { (char*) "America/Rosario" , 0x0348FD }, + { (char*) "America/Santa_Isabel" , 0x034D2F }, + { (char*) "America/Santarem" , 0x0356D5 }, + { (char*) "America/Santiago" , 0x035938 }, + { (char*) "America/Santo_Domingo" , 0x036324 }, + { (char*) "America/Sao_Paulo" , 0x0364FA }, + { (char*) "America/Scoresbysund" , 0x036AD2 }, + { (char*) "America/Shiprock" , 0x03728A }, + { (char*) "America/Sitka" , 0x037C32 }, + { (char*) "America/St_Barthelemy" , 0x03856A }, + { (char*) "America/St_Johns" , 0x03866C }, + { (char*) "America/St_Kitts" , 0x0394DA }, + { (char*) "America/St_Lucia" , 0x03957A }, + { (char*) "America/St_Thomas" , 0x03963C }, + { (char*) "America/St_Vincent" , 0x0396DC }, + { (char*) "America/Swift_Current" , 0x03979E }, + { (char*) "America/Tegucigalpa" , 0x0399EC }, + { (char*) "America/Thule" , 0x039AF4 }, + { (char*) "America/Thunder_Bay" , 0x03A0EC }, + { (char*) "America/Tijuana" , 0x03AE9E }, + { (char*) "America/Toronto" , 0x03B853 }, + { (char*) "America/Tortola" , 0x03C623 }, + { (char*) "America/Vancouver" , 0x03C6C3 }, + { (char*) "America/Virgin" , 0x03D234 }, + { (char*) "America/Whitehorse" , 0x03D336 }, + { (char*) "America/Winnipeg" , 0x03D9A2 }, + { (char*) "America/Yakutat" , 0x03E4FF }, + { (char*) "America/Yellowknife" , 0x03EE1C }, + { (char*) "Antarctica/Casey" , 0x03F744 }, + { (char*) "Antarctica/Davis" , 0x03F8FC }, + { (char*) "Antarctica/DumontDUrville" , 0x03FA28 }, + { (char*) "Antarctica/Macquarie" , 0x03FAF8 }, + { (char*) "Antarctica/Mawson" , 0x0403E8 }, + { (char*) "Antarctica/McMurdo" , 0x0404B3 }, + { (char*) "Antarctica/Palmer" , 0x040CAE }, + { (char*) "Antarctica/Rothera" , 0x04123C }, + { (char*) "Antarctica/South_Pole" , 0x0412E5 }, + { (char*) "Antarctica/Syowa" , 0x041C76 }, + { (char*) "Antarctica/Troll" , 0x041D1E }, + { (char*) "Antarctica/Vostok" , 0x0421AB }, + { (char*) "Arctic/Longyearbyen" , 0x042292 }, + { (char*) "Asia/Aden" , 0x042B98 }, + { (char*) "Asia/Almaty" , 0x042C3B }, + { (char*) "Asia/Amman" , 0x043030 }, + { (char*) "Asia/Anadyr" , 0x0435D5 }, + { (char*) "Asia/Aqtau" , 0x043A8A }, + { (char*) "Asia/Aqtobe" , 0x043E74 }, + { (char*) "Asia/Ashgabat" , 0x044272 }, + { (char*) "Asia/Ashkhabad" , 0x0444DB }, + { (char*) "Asia/Atyrau" , 0x044744 }, + { (char*) "Asia/Baghdad" , 0x044B36 }, + { (char*) "Asia/Bahrain" , 0x044F0B }, + { (char*) "Asia/Baku" , 0x044FF6 }, + { (char*) "Asia/Bangkok" , 0x0454BF }, + { (char*) "Asia/Barnaul" , 0x045584 }, + { (char*) "Asia/Beirut" , 0x045A55 }, + { (char*) "Asia/Bishkek" , 0x0462CB }, + { (char*) "Asia/Brunei" , 0x0466A0 }, + { (char*) "Asia/Calcutta" , 0x046769 }, + { (char*) "Asia/Chita" , 0x046892 }, + { (char*) "Asia/Choibalsan" , 0x046D69 }, + { (char*) "Asia/Chongqing" , 0x0470E2 }, + { (char*) "Asia/Chungking" , 0x04731F }, + { (char*) "Asia/Colombo" , 0x04755C }, + { (char*) "Asia/Dacca" , 0x0476CE }, + { (char*) "Asia/Damascus" , 0x04781D }, + { (char*) "Asia/Dhaka" , 0x047F7A }, + { (char*) "Asia/Dili" , 0x0480C9 }, + { (char*) "Asia/Dubai" , 0x0481D6 }, + { (char*) "Asia/Dushanbe" , 0x048279 }, + { (char*) "Asia/Famagusta" , 0x0484C6 }, + { (char*) "Asia/Gaza" , 0x048CCD }, + { (char*) "Asia/Harbin" , 0x049BE7 }, + { (char*) "Asia/Hebron" , 0x049E24 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x04AD59 }, + { (char*) "Asia/Hong_Kong" , 0x04AEB6 }, + { (char*) "Asia/Hovd" , 0x04B393 }, + { (char*) "Asia/Irkutsk" , 0x04B722 }, + { (char*) "Asia/Istanbul" , 0x04BC15 }, + { (char*) "Asia/Jakarta" , 0x04C3AE }, + { (char*) "Asia/Jayapura" , 0x04C546 }, + { (char*) "Asia/Jerusalem" , 0x04C665 }, + { (char*) "Asia/Kabul" , 0x04CFC5 }, + { (char*) "Asia/Kamchatka" , 0x04D093 }, + { (char*) "Asia/Karachi" , 0x04D531 }, + { (char*) "Asia/Kashgar" , 0x04D6B8 }, + { (char*) "Asia/Kathmandu" , 0x04D75B }, + { (char*) "Asia/Katmandu" , 0x04D82D }, + { (char*) "Asia/Khandyga" , 0x04D8FF }, + { (char*) "Asia/Kolkata" , 0x04DE12 }, + { (char*) "Asia/Krasnoyarsk" , 0x04DF3B }, + { (char*) "Asia/Kuala_Lumpur" , 0x04E409 }, + { (char*) "Asia/Kuching" , 0x04E5BA }, + { (char*) "Asia/Kuwait" , 0x04E7A9 }, + { (char*) "Asia/Macao" , 0x04E84C }, + { (char*) "Asia/Macau" , 0x04ED23 }, + { (char*) "Asia/Magadan" , 0x04F1FA }, + { (char*) "Asia/Makassar" , 0x04F6CE }, + { (char*) "Asia/Manila" , 0x04F821 }, + { (char*) "Asia/Muscat" , 0x04F9D3 }, + { (char*) "Asia/Nicosia" , 0x04FA76 }, + { (char*) "Asia/Novokuznetsk" , 0x050262 }, + { (char*) "Asia/Novosibirsk" , 0x0506FE }, + { (char*) "Asia/Omsk" , 0x050BD5 }, + { (char*) "Asia/Oral" , 0x051097 }, + { (char*) "Asia/Phnom_Penh" , 0x051491 }, + { (char*) "Asia/Pontianak" , 0x0515B6 }, + { (char*) "Asia/Pyongyang" , 0x051739 }, + { (char*) "Asia/Qatar" , 0x051832 }, + { (char*) "Asia/Qostanay" , 0x0518F7 }, + { (char*) "Asia/Qyzylorda" , 0x051D1E }, + { (char*) "Asia/Rangoon" , 0x05213A }, + { (char*) "Asia/Riyadh" , 0x052244 }, + { (char*) "Asia/Saigon" , 0x0522E7 }, + { (char*) "Asia/Sakhalin" , 0x052444 }, + { (char*) "Asia/Samarkand" , 0x05290C }, + { (char*) "Asia/Seoul" , 0x052B5C }, + { (char*) "Asia/Shanghai" , 0x052DD1 }, + { (char*) "Asia/Singapore" , 0x05301A }, + { (char*) "Asia/Srednekolymsk" , 0x0531B7 }, + { (char*) "Asia/Taipei" , 0x05368B }, + { (char*) "Asia/Tashkent" , 0x053990 }, + { (char*) "Asia/Tbilisi" , 0x053BEE }, + { (char*) "Asia/Tehran" , 0x053FF7 }, + { (char*) "Asia/Tel_Aviv" , 0x0544E3 }, + { (char*) "Asia/Thimbu" , 0x054E43 }, + { (char*) "Asia/Thimphu" , 0x054F0C }, + { (char*) "Asia/Tokyo" , 0x054FD5 }, + { (char*) "Asia/Tomsk" , 0x055116 }, + { (char*) "Asia/Ujung_Pandang" , 0x0555E7 }, + { (char*) "Asia/Ulaanbaatar" , 0x0556F1 }, + { (char*) "Asia/Ulan_Bator" , 0x055A7A }, + { (char*) "Asia/Urumqi" , 0x055DF3 }, + { (char*) "Asia/Ust-Nera" , 0x055EA3 }, + { (char*) "Asia/Vientiane" , 0x056399 }, + { (char*) "Asia/Vladivostok" , 0x0564DA }, + { (char*) "Asia/Yakutsk" , 0x0569A3 }, + { (char*) "Asia/Yangon" , 0x056E6B }, + { (char*) "Asia/Yekaterinburg" , 0x056F75 }, + { (char*) "Asia/Yerevan" , 0x05745C }, + { (char*) "Atlantic/Azores" , 0x0578D9 }, + { (char*) "Atlantic/Bermuda" , 0x05865D }, + { (char*) "Atlantic/Canary" , 0x058FC5 }, + { (char*) "Atlantic/Cape_Verde" , 0x059748 }, + { (char*) "Atlantic/Faeroe" , 0x059854 }, + { (char*) "Atlantic/Faroe" , 0x059F77 }, + { (char*) "Atlantic/Jan_Mayen" , 0x05A69A }, + { (char*) "Atlantic/Madeira" , 0x05AFA0 }, + { (char*) "Atlantic/Reykjavik" , 0x05BCEC }, + { (char*) "Atlantic/South_Georgia" , 0x05C182 }, + { (char*) "Atlantic/St_Helena" , 0x05C224 }, + { (char*) "Atlantic/Stanley" , 0x05C2E6 }, + { (char*) "Australia/ACT" , 0x05C7A2 }, + { (char*) "Australia/Adelaide" , 0x05D03C }, + { (char*) "Australia/Brisbane" , 0x05D8F7 }, + { (char*) "Australia/Broken_Hill" , 0x05DABD }, + { (char*) "Australia/Canberra" , 0x05E39A }, + { (char*) "Australia/Currie" , 0x05EC34 }, + { (char*) "Australia/Darwin" , 0x05F576 }, + { (char*) "Australia/Eucla" , 0x05F6D9 }, + { (char*) "Australia/Hobart" , 0x05F8C6 }, + { (char*) "Australia/LHI" , 0x060210 }, + { (char*) "Australia/Lindeman" , 0x060952 }, + { (char*) "Australia/Lord_Howe" , 0x060B58 }, + { (char*) "Australia/Melbourne" , 0x0612AA }, + { (char*) "Australia/North" , 0x061B4C }, + { (char*) "Australia/NSW" , 0x061C9D }, + { (char*) "Australia/Perth" , 0x062537 }, + { (char*) "Australia/Queensland" , 0x06271F }, + { (char*) "Australia/South" , 0x0628CE }, + { (char*) "Australia/Sydney" , 0x06317A }, + { (char*) "Australia/Tasmania" , 0x063A30 }, + { (char*) "Australia/Victoria" , 0x064372 }, + { (char*) "Australia/West" , 0x064C0C }, + { (char*) "Australia/Yancowinna" , 0x064DD6 }, + { (char*) "Brazil/Acre" , 0x065697 }, + { (char*) "Brazil/DeNoronha" , 0x065909 }, + { (char*) "Brazil/East" , 0x065BD3 }, + { (char*) "Brazil/West" , 0x066175 }, + { (char*) "Canada/Atlantic" , 0x0663CF }, + { (char*) "Canada/Central" , 0x06713B }, + { (char*) "Canada/Eastern" , 0x067C7B }, + { (char*) "Canada/Mountain" , 0x068A2D }, + { (char*) "Canada/Newfoundland" , 0x069355 }, + { (char*) "Canada/Pacific" , 0x06A1A8 }, + { (char*) "Canada/Saskatchewan" , 0x06AD00 }, + { (char*) "Canada/Yukon" , 0x06B0E0 }, + { (char*) "CET" , 0x06B73A }, + { (char*) "Chile/Continental" , 0x06C2BB }, + { (char*) "Chile/EasterIsland" , 0x06CC9A }, + { (char*) "CST6CDT" , 0x06D551 }, + { (char*) "Cuba" , 0x06E365 }, + { (char*) "EET" , 0x06ECE1 }, + { (char*) "Egypt" , 0x06F5C3 }, + { (char*) "Eire" , 0x06FF2E }, + { (char*) "EST" , 0x070CDE }, + { (char*) "EST5EDT" , 0x070DA0 }, + { (char*) "Etc/GMT" , 0x071B8C }, + { (char*) "Etc/GMT+0" , 0x071C0A }, + { (char*) "Etc/GMT+1" , 0x071C88 }, + { (char*) "Etc/GMT+10" , 0x071D08 }, + { (char*) "Etc/GMT+11" , 0x071D89 }, + { (char*) "Etc/GMT+12" , 0x071E0A }, + { (char*) "Etc/GMT+2" , 0x071E8B }, + { (char*) "Etc/GMT+3" , 0x071F0B }, + { (char*) "Etc/GMT+4" , 0x071F8B }, + { (char*) "Etc/GMT+5" , 0x07200B }, + { (char*) "Etc/GMT+6" , 0x07208B }, + { (char*) "Etc/GMT+7" , 0x07210B }, + { (char*) "Etc/GMT+8" , 0x07218B }, + { (char*) "Etc/GMT+9" , 0x07220B }, + { (char*) "Etc/GMT-0" , 0x07228B }, + { (char*) "Etc/GMT-1" , 0x072309 }, + { (char*) "Etc/GMT-10" , 0x07238A }, + { (char*) "Etc/GMT-11" , 0x07240C }, + { (char*) "Etc/GMT-12" , 0x07248E }, + { (char*) "Etc/GMT-13" , 0x072510 }, + { (char*) "Etc/GMT-14" , 0x072592 }, + { (char*) "Etc/GMT-2" , 0x072614 }, + { (char*) "Etc/GMT-3" , 0x072695 }, + { (char*) "Etc/GMT-4" , 0x072716 }, + { (char*) "Etc/GMT-5" , 0x072797 }, + { (char*) "Etc/GMT-6" , 0x072818 }, + { (char*) "Etc/GMT-7" , 0x072899 }, + { (char*) "Etc/GMT-8" , 0x07291A }, + { (char*) "Etc/GMT-9" , 0x07299B }, + { (char*) "Etc/GMT0" , 0x072A1C }, + { (char*) "Etc/Greenwich" , 0x072A9A }, + { (char*) "Etc/UCT" , 0x072B18 }, + { (char*) "Etc/Universal" , 0x072B96 }, + { (char*) "Etc/UTC" , 0x072C14 }, + { (char*) "Etc/Zulu" , 0x072C92 }, + { (char*) "Europe/Amsterdam" , 0x072D10 }, + { (char*) "Europe/Andorra" , 0x07387A }, + { (char*) "Europe/Astrakhan" , 0x073F54 }, + { (char*) "Europe/Athens" , 0x0743F1 }, + { (char*) "Europe/Belfast" , 0x074CD3 }, + { (char*) "Europe/Belgrade" , 0x075B2F }, + { (char*) "Europe/Berlin" , 0x0762BB }, + { (char*) "Europe/Bratislava" , 0x076BD0 }, + { (char*) "Europe/Brussels" , 0x0774D9 }, + { (char*) "Europe/Bucharest" , 0x07805A }, + { (char*) "Europe/Budapest" , 0x0788EE }, + { (char*) "Europe/Busingen" , 0x07923A }, + { (char*) "Europe/Chisinau" , 0x0799C3 }, + { (char*) "Europe/Copenhagen" , 0x07A325 }, + { (char*) "Europe/Dublin" , 0x07AB8A }, + { (char*) "Europe/Gibraltar" , 0x07B93A }, + { (char*) "Europe/Guernsey" , 0x07C542 }, + { (char*) "Europe/Helsinki" , 0x07D3E2 }, + { (char*) "Europe/Isle_of_Man" , 0x07DB5A }, + { (char*) "Europe/Istanbul" , 0x07E9A6 }, + { (char*) "Europe/Jersey" , 0x07F13F }, + { (char*) "Europe/Kaliningrad" , 0x07FFDF }, + { (char*) "Europe/Kiev" , 0x0805D4 }, + { (char*) "Europe/Kirov" , 0x080E28 }, + { (char*) "Europe/Kyiv" , 0x0812E3 }, + { (char*) "Europe/Lisbon" , 0x081B46 }, + { (char*) "Europe/Ljubljana" , 0x08292C }, + { (char*) "Europe/London" , 0x0830B8 }, + { (char*) "Europe/Luxembourg" , 0x083F14 }, + { (char*) "Europe/Madrid" , 0x084AA2 }, + { (char*) "Europe/Malta" , 0x0854F4 }, + { (char*) "Europe/Mariehamn" , 0x085F3C }, + { (char*) "Europe/Minsk" , 0x0866B4 }, + { (char*) "Europe/Monaco" , 0x086BDB }, + { (char*) "Europe/Moscow" , 0x087767 }, + { (char*) "Europe/Nicosia" , 0x087D86 }, + { (char*) "Europe/Oslo" , 0x088564 }, + { (char*) "Europe/Paris" , 0x088E24 }, + { (char*) "Europe/Podgorica" , 0x0899C2 }, + { (char*) "Europe/Prague" , 0x08A14E }, + { (char*) "Europe/Riga" , 0x08AA57 }, + { (char*) "Europe/Rome" , 0x08B2F9 }, + { (char*) "Europe/Samara" , 0x08BD56 }, + { (char*) "Europe/San_Marino" , 0x08C22C }, + { (char*) "Europe/Sarajevo" , 0x08CC89 }, + { (char*) "Europe/Saratov" , 0x08D415 }, + { (char*) "Europe/Simferopol" , 0x08D8C2 }, + { (char*) "Europe/Skopje" , 0x08DE91 }, + { (char*) "Europe/Sofia" , 0x08E61D }, + { (char*) "Europe/Stockholm" , 0x08EE46 }, + { (char*) "Europe/Tallinn" , 0x08F5C7 }, + { (char*) "Europe/Tirane" , 0x08FE37 }, + { (char*) "Europe/Tiraspol" , 0x090667 }, + { (char*) "Europe/Ulyanovsk" , 0x090FC9 }, + { (char*) "Europe/Uzhgorod" , 0x0914CC }, + { (char*) "Europe/Vaduz" , 0x091D20 }, + { (char*) "Europe/Vatican" , 0x09248C }, + { (char*) "Europe/Vienna" , 0x092EE9 }, + { (char*) "Europe/Vilnius" , 0x09378D }, + { (char*) "Europe/Volgograd" , 0x09400B }, + { (char*) "Europe/Warsaw" , 0x0944D2 }, + { (char*) "Europe/Zagreb" , 0x094F3C }, + { (char*) "Europe/Zaporozhye" , 0x0956C8 }, + { (char*) "Europe/Zurich" , 0x095F1C }, + { (char*) "Factory" , 0x09669D }, + { (char*) "GB" , 0x09671D }, + { (char*) "GB-Eire" , 0x097579 }, + { (char*) "GMT" , 0x0983D5 }, + { (char*) "GMT+0" , 0x098453 }, + { (char*) "GMT-0" , 0x0984D1 }, + { (char*) "GMT0" , 0x09854F }, + { (char*) "Greenwich" , 0x0985CD }, + { (char*) "Hongkong" , 0x09864B }, + { (char*) "HST" , 0x098B28 }, + { (char*) "Iceland" , 0x098C7D }, + { (char*) "Indian/Antananarivo" , 0x098D1D }, + { (char*) "Indian/Chagos" , 0x098E04 }, + { (char*) "Indian/Christmas" , 0x098EC9 }, + { (char*) "Indian/Cocos" , 0x098F6C }, + { (char*) "Indian/Comoro" , 0x099018 }, + { (char*) "Indian/Kerguelen" , 0x0990B9 }, + { (char*) "Indian/Mahe" , 0x09915C }, + { (char*) "Indian/Maldives" , 0x0991FF }, + { (char*) "Indian/Mauritius" , 0x0992C4 }, + { (char*) "Indian/Mayotte" , 0x0993B3 }, + { (char*) "Indian/Reunion" , 0x099454 }, + { (char*) "Iran" , 0x0994F7 }, + { (char*) "Israel" , 0x0999E3 }, + { (char*) "Jamaica" , 0x09A343 }, + { (char*) "Japan" , 0x09A531 }, + { (char*) "Kwajalein" , 0x09A672 }, + { (char*) "Libya" , 0x09A7AC }, + { (char*) "MET" , 0x09AA29 }, + { (char*) "Mexico/BajaNorte" , 0x09B5AA }, + { (char*) "Mexico/BajaSur" , 0x09BF50 }, + { (char*) "Mexico/General" , 0x09C380 }, + { (char*) "MST" , 0x09C852 }, + { (char*) "MST7MDT" , 0x09C9C6 }, + { (char*) "Navajo" , 0x09D36E }, + { (char*) "NZ" , 0x09DD16 }, + { (char*) "NZ-CHAT" , 0x09E6A7 }, + { (char*) "Pacific/Apia" , 0x09EEB9 }, + { (char*) "Pacific/Auckland" , 0x09F11B }, + { (char*) "Pacific/Bougainville" , 0x09FABF }, + { (char*) "Pacific/Chatham" , 0x09FBD5 }, + { (char*) "Pacific/Chuuk" , 0x0A03F6 }, + { (char*) "Pacific/Easter" , 0x0A0510 }, + { (char*) "Pacific/Efate" , 0x0A0DD4 }, + { (char*) "Pacific/Enderbury" , 0x0A0FEC }, + { (char*) "Pacific/Fakaofo" , 0x0A10D4 }, + { (char*) "Pacific/Fiji" , 0x0A119A }, + { (char*) "Pacific/Funafuti" , 0x0A13DA }, + { (char*) "Pacific/Galapagos" , 0x0A147E }, + { (char*) "Pacific/Gambier" , 0x0A157B }, + { (char*) "Pacific/Guadalcanal" , 0x0A162C }, + { (char*) "Pacific/Guam" , 0x0A16D0 }, + { (char*) "Pacific/Honolulu" , 0x0A18CA }, + { (char*) "Pacific/Johnston" , 0x0A1A25 }, + { (char*) "Pacific/Kanton" , 0x0A1B7A }, + { (char*) "Pacific/Kiritimati" , 0x0A1C71 }, + { (char*) "Pacific/Kosrae" , 0x0A1D69 }, + { (char*) "Pacific/Kwajalein" , 0x0A1ECC }, + { (char*) "Pacific/Majuro" , 0x0A200F }, + { (char*) "Pacific/Marquesas" , 0x0A215B }, + { (char*) "Pacific/Midway" , 0x0A2217 }, + { (char*) "Pacific/Nauru" , 0x0A230A }, + { (char*) "Pacific/Niue" , 0x0A2404 }, + { (char*) "Pacific/Norfolk" , 0x0A24CD }, + { (char*) "Pacific/Noumea" , 0x0A283B }, + { (char*) "Pacific/Pago_Pago" , 0x0A2969 }, + { (char*) "Pacific/Palau" , 0x0A2A24 }, + { (char*) "Pacific/Pitcairn" , 0x0A2AD6 }, + { (char*) "Pacific/Pohnpei" , 0x0A2B9E }, + { (char*) "Pacific/Ponape" , 0x0A2CD9 }, + { (char*) "Pacific/Port_Moresby" , 0x0A2D7D }, + { (char*) "Pacific/Rarotonga" , 0x0A2E4D }, + { (char*) "Pacific/Saipan" , 0x0A30A6 }, + { (char*) "Pacific/Samoa" , 0x0A3292 }, + { (char*) "Pacific/Tahiti" , 0x0A334D }, + { (char*) "Pacific/Tarawa" , 0x0A33FF }, + { (char*) "Pacific/Tongatapu" , 0x0A34B2 }, + { (char*) "Pacific/Truk" , 0x0A3624 }, + { (char*) "Pacific/Wake" , 0x0A36DC }, + { (char*) "Pacific/Wallis" , 0x0A378B }, + { (char*) "Pacific/Yap" , 0x0A382F }, + { (char*) "Poland" , 0x0A38E7 }, + { (char*) "Portugal" , 0x0A4351 }, + { (char*) "PRC" , 0x0A5124 }, + { (char*) "PST8PDT" , 0x0A5361 }, + { (char*) "ROC" , 0x0A5E91 }, + { (char*) "ROK" , 0x0A6196 }, + { (char*) "Singapore" , 0x0A640B }, + { (char*) "Turkey" , 0x0A65A8 }, + { (char*) "UCT" , 0x0A6D41 }, + { (char*) "Universal" , 0x0A6DBF }, + { (char*) "US/Alaska" , 0x0A6E3D }, + { (char*) "US/Aleutian" , 0x0A778C }, + { (char*) "US/Arizona" , 0x0A80CC }, + { (char*) "US/Central" , 0x0A8240 }, + { (char*) "US/East-Indiana" , 0x0A9054 }, + { (char*) "US/Eastern" , 0x0A96F2 }, + { (char*) "US/Hawaii" , 0x0AA4DE }, + { (char*) "US/Indiana-Starke" , 0x0AA633 }, + { (char*) "US/Michigan" , 0x0AAFCB }, + { (char*) "US/Mountain" , 0x0AB88D }, + { (char*) "US/Pacific" , 0x0AC235 }, + { (char*) "US/Samoa" , 0x0ACD65 }, + { (char*) "UTC" , 0x0ACE20 }, + { (char*) "W-SU" , 0x0ACE9E }, + { (char*) "WET" , 0x0AD4A9 }, + { (char*) "Zulu" , 0x0AE27C }, }; -const unsigned char timelib_timezone_db_data_builtin[711319] = { +const unsigned char timelib_timezone_db_data_builtin[713466] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -29630,6 +29720,143 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x54, 0x00, 0x43, 0x53, 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, +0x8F, 0x30, 0x47, 0x45, 0x9B, 0x5C, 0xE5, 0x50, 0x9F, 0x7C, 0xE2, 0xC5, 0xA1, 0x00, 0x71, 0xC0, +0xB0, 0x5E, 0x77, 0xC5, 0xB1, 0x77, 0x3D, 0x40, 0xB2, 0x41, 0x00, 0xD0, 0xB3, 0x58, 0x70, 0xC0, +0xB4, 0x22, 0x34, 0x50, 0xB5, 0x39, 0xA4, 0x40, 0xB6, 0x03, 0x67, 0xD0, 0xB7, 0x1A, 0xD7, 0xC0, +0xB7, 0xE4, 0x9B, 0x50, 0xB8, 0xFD, 0x5C, 0xC0, 0xB9, 0xC7, 0x20, 0x50, 0xCC, 0x1C, 0x6E, 0x40, +0xCC, 0x6C, 0xE7, 0xD0, 0xD4, 0x17, 0xE3, 0x40, 0xD5, 0x33, 0x55, 0xC0, 0xD5, 0x76, 0x92, 0x40, +0xFD, 0xD1, 0x3C, 0x40, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x72, 0xDC, 0xB0, +0x01, 0x75, 0x50, 0xC0, 0x02, 0x40, 0x49, 0xB0, 0x03, 0x55, 0x32, 0xC0, 0x04, 0x20, 0x2B, 0xB0, +0x05, 0x3E, 0x4F, 0x40, 0x06, 0x00, 0x0D, 0xB0, 0x07, 0x0B, 0xBC, 0x40, 0x07, 0xDF, 0xEF, 0xB0, +0x08, 0xFE, 0x13, 0x40, 0x09, 0xBF, 0xD1, 0xB0, 0x0A, 0xDD, 0xF5, 0x40, 0x0B, 0xA8, 0xEE, 0x30, +0x0C, 0xBD, 0xD7, 0x40, 0x0D, 0x88, 0xD0, 0x30, 0x0E, 0x9D, 0xB9, 0x40, 0x0F, 0x68, 0xB2, 0x30, +0x10, 0x86, 0xD5, 0xC0, 0x11, 0x48, 0x94, 0x30, 0x12, 0x66, 0xB7, 0xC0, 0x13, 0x28, 0x76, 0x30, +0x14, 0x46, 0x99, 0xC0, 0x15, 0x11, 0x92, 0xB0, 0x16, 0x26, 0x7B, 0xC0, 0x16, 0xF1, 0x74, 0xB0, +0x18, 0x06, 0x5D, 0xC0, 0x18, 0xD1, 0x56, 0xB0, 0x19, 0xE6, 0x3F, 0xC0, 0x1A, 0xB1, 0x38, 0xB0, +0x1B, 0xCF, 0x5C, 0x40, 0x1C, 0x91, 0x1A, 0xB0, 0x1D, 0xAF, 0x3E, 0x40, 0x1E, 0x70, 0xFC, 0xB0, +0x1F, 0x8F, 0x20, 0x40, 0x20, 0x7F, 0x03, 0x30, 0x21, 0x6F, 0x02, 0x40, 0x22, 0x39, 0xFB, 0x30, +0x23, 0x4E, 0xE4, 0x40, 0x24, 0x19, 0xDD, 0x30, 0x25, 0x38, 0x00, 0xC0, 0x25, 0xF9, 0xBF, 0x30, +0x26, 0xF2, 0xF8, 0xC0, 0x27, 0xD9, 0xA1, 0x30, 0x28, 0xF7, 0xC4, 0xC0, 0x29, 0xC2, 0xBD, 0xB0, +0x2A, 0xD7, 0xA6, 0xC0, 0x2B, 0xA2, 0x9F, 0xB0, 0x2C, 0xB7, 0x88, 0xC0, 0x2D, 0x82, 0x81, 0xB0, +0x2E, 0x97, 0x6A, 0xC0, 0x2F, 0x62, 0x63, 0xB0, 0x30, 0x80, 0x87, 0x40, 0x31, 0x42, 0x45, 0xB0, +0x32, 0x60, 0x69, 0x40, 0x33, 0x3D, 0xD7, 0x30, 0x34, 0x40, 0x4B, 0x40, 0x35, 0x0B, 0x44, 0x30, +0x36, 0x0D, 0xB8, 0x40, 0x37, 0x06, 0xD5, 0xB0, 0x38, 0x00, 0x0F, 0x40, 0x38, 0xCB, 0x08, 0x30, +0x39, 0xE9, 0x2B, 0xC0, 0x3A, 0xAA, 0xEA, 0x30, 0x3B, 0xC9, 0x0D, 0xC0, 0x3C, 0x8A, 0xCC, 0x30, +0x3D, 0xA8, 0xEF, 0xC0, 0x3E, 0x6A, 0xAE, 0x30, 0x3F, 0x88, 0xD1, 0xC0, 0x40, 0x53, 0xCA, 0xB0, +0x41, 0x68, 0xB3, 0xC0, 0x42, 0x33, 0xAC, 0xB0, 0x43, 0x48, 0x95, 0xC0, 0x44, 0x13, 0x8E, 0xB0, +0x45, 0x31, 0xB2, 0x40, 0x45, 0xF3, 0x70, 0xB0, 0x47, 0x11, 0x94, 0x40, 0x47, 0xEF, 0x02, 0x30, +0x48, 0xF1, 0x76, 0x40, 0x49, 0xBC, 0x6F, 0x30, 0x4A, 0xD1, 0x58, 0x40, 0x4B, 0xB8, 0x00, 0xB0, +0x4C, 0xB1, 0x3A, 0x40, 0x4D, 0xC6, 0x07, 0x30, 0x4E, 0x50, 0x82, 0xC0, 0x4F, 0x9C, 0xAE, 0xB0, +0x50, 0x42, 0xD9, 0xC0, 0x51, 0x7C, 0x90, 0xB0, 0x52, 0x2B, 0xF6, 0x40, 0x53, 0x5C, 0x72, 0xB0, +0x54, 0x0B, 0xD8, 0x40, 0x57, 0x37, 0xE6, 0x30, 0x57, 0xAF, 0xEC, 0xC0, 0x59, 0x17, 0xC8, 0x30, +0x59, 0x8F, 0xCE, 0xC0, 0x5A, 0xF7, 0xAA, 0x30, 0x5B, 0x6F, 0xB0, 0xC0, 0x5C, 0xA9, 0x67, 0xB0, +0x5D, 0x74, 0x7C, 0xC0, 0x5E, 0x89, 0x49, 0xB0, 0x5F, 0x54, 0x5E, 0xC0, 0x60, 0x69, 0x2B, 0xB0, +0x61, 0x34, 0x40, 0xC0, 0x62, 0x49, 0x0D, 0xB0, 0x63, 0x1D, 0x5D, 0x40, 0x64, 0x28, 0xEF, 0xB0, +0x64, 0xF4, 0x04, 0xC0, 0x66, 0x12, 0x0C, 0x30, 0x66, 0xDD, 0x21, 0x40, 0x67, 0xDB, 0x84, 0xB0, +0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, +0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, +0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, +0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, +0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, +0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, +0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, +0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, 0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, 0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, +0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, +0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, +0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, +0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, +0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, +0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, +0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, +0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x30, 0x80, 0x87, 0x40, 0x00, 0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x32, 0x60, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, +0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, +0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, +0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x47, 0x11, 0x94, 0x40, 0x00, 0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, +0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, 0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, +0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, +0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, +0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, +0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, +0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, +0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, +0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, +0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, +0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x43, +0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, 0x73, 0x65, 0x6E, 0x20, +0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -38062,8 +38289,8 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x38, -0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, -0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, +0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, +0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -47037,7 +47264,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -47068,7 +47295,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -65285,7 +65512,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -65316,7 +65543,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -70844,4 +71071,4 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { }; #endif -const timelib_tzdb timezonedb_builtin = { "2025.1", 597, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; +const timelib_tzdb timezonedb_builtin = { "2025.2", 598, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; From 2d30c2e1ad627baf0bf41858073eaadf15fc450d Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 24 Mar 2025 10:06:36 +0000 Subject: [PATCH 156/503] Updated to version 2025.2 (2025b) --- ext/date/lib/timezonedb.h | 2251 ++++++++++++++++++++----------------- 1 file changed, 1239 insertions(+), 1012 deletions(-) diff --git a/ext/date/lib/timezonedb.h b/ext/date/lib/timezonedb.h index 3c75462009afb..a4cbb618799c8 100644 --- a/ext/date/lib/timezonedb.h +++ b/ext/date/lib/timezonedb.h @@ -4,7 +4,7 @@ #endif #ifdef TIMELIB_SUPPORT_SLIM_FILE -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x00008E }, { (char*) "Africa/Addis_Ababa" , 0x000356 }, @@ -104,508 +104,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x00ADD3 }, { (char*) "America/Cordoba" , 0x00AE74 }, { (char*) "America/Costa_Rica" , 0x00B144 }, - { (char*) "America/Creston" , 0x00B238 }, - { (char*) "America/Cuiaba" , 0x00B2F4 }, - { (char*) "America/Curacao" , 0x00B6B1 }, - { (char*) "America/Danmarkshavn" , 0x00B754 }, - { (char*) "America/Dawson" , 0x00B939 }, - { (char*) "America/Dawson_Creek" , 0x00BD5C }, - { (char*) "America/Denver" , 0x00C033 }, - { (char*) "America/Detroit" , 0x00C466 }, - { (char*) "America/Dominica" , 0x00C80E }, - { (char*) "America/Edmonton" , 0x00C89C }, - { (char*) "America/Eirunepe" , 0x00CC94 }, - { (char*) "America/El_Salvador" , 0x00CE63 }, - { (char*) "America/Ensenada" , 0x00CF1F }, - { (char*) "America/Fort_Nelson" , 0x00D362 }, - { (char*) "America/Fort_Wayne" , 0x00D92A }, - { (char*) "America/Fortaleza" , 0x00DB49 }, - { (char*) "America/Glace_Bay" , 0x00DD5F }, - { (char*) "America/Godthab" , 0x00E0F6 }, - { (char*) "America/Goose_Bay" , 0x00E4C7 }, - { (char*) "America/Grand_Turk" , 0x00EB1F }, - { (char*) "America/Grenada" , 0x00EE80 }, - { (char*) "America/Guadeloupe" , 0x00EF0E }, - { (char*) "America/Guatemala" , 0x00EF9C }, - { (char*) "America/Guayaquil" , 0x00F07C }, - { (char*) "America/Guyana" , 0x00F14D }, - { (char*) "America/Halifax" , 0x00F20E }, - { (char*) "America/Havana" , 0x00F8C0 }, - { (char*) "America/Hermosillo" , 0x00FD29 }, - { (char*) "America/Indiana/Indianapolis" , 0x00FE3D }, - { (char*) "America/Indiana/Knox" , 0x010075 }, - { (char*) "America/Indiana/Marengo" , 0x01048E }, - { (char*) "America/Indiana/Petersburg" , 0x0106E8 }, - { (char*) "America/Indiana/Tell_City" , 0x0109B2 }, - { (char*) "America/Indiana/Vevay" , 0x010BDC }, - { (char*) "America/Indiana/Vincennes" , 0x010D73 }, - { (char*) "America/Indiana/Winamac" , 0x010FC9 }, - { (char*) "America/Indianapolis" , 0x011246 }, - { (char*) "America/Inuvik" , 0x011465 }, - { (char*) "America/Iqaluit" , 0x0117B6 }, - { (char*) "America/Jamaica" , 0x011B32 }, - { (char*) "America/Jujuy" , 0x011C91 }, - { (char*) "America/Juneau" , 0x011F4F }, - { (char*) "America/Kentucky/Louisville" , 0x012335 }, - { (char*) "America/Kentucky/Monticello" , 0x012839 }, - { (char*) "America/Knox_IN" , 0x012C25 }, - { (char*) "America/Kralendijk" , 0x013029 }, - { (char*) "America/La_Paz" , 0x0130E6 }, - { (char*) "America/Lima" , 0x01319C }, - { (char*) "America/Los_Angeles" , 0x0132C3 }, - { (char*) "America/Louisville" , 0x0137E4 }, - { (char*) "America/Lower_Princes" , 0x013CCA }, - { (char*) "America/Maceio" , 0x013D87 }, - { (char*) "America/Managua" , 0x013F99 }, - { (char*) "America/Manaus" , 0x0140CC }, - { (char*) "America/Marigot" , 0x014283 }, - { (char*) "America/Martinique" , 0x014340 }, - { (char*) "America/Matamoros" , 0x0143FE }, - { (char*) "America/Mazatlan" , 0x0145EB }, - { (char*) "America/Mendoza" , 0x0148DB }, - { (char*) "America/Menominee" , 0x014BAB }, - { (char*) "America/Merida" , 0x014F6B }, - { (char*) "America/Metlakatla" , 0x015216 }, - { (char*) "America/Mexico_City" , 0x015483 }, - { (char*) "America/Miquelon" , 0x0157A2 }, - { (char*) "America/Moncton" , 0x0159D4 }, - { (char*) "America/Monterrey" , 0x015FCD }, - { (char*) "America/Montevideo" , 0x0162D4 }, - { (char*) "America/Montreal" , 0x0166A9 }, - { (char*) "America/Montserrat" , 0x016D6A }, - { (char*) "America/Nassau" , 0x016DF8 }, - { (char*) "America/New_York" , 0x0171F2 }, - { (char*) "America/Nipigon" , 0x0178E2 }, - { (char*) "America/Nome" , 0x017FA3 }, - { (char*) "America/Noronha" , 0x01838B }, - { (char*) "America/North_Dakota/Beulah" , 0x01858B }, - { (char*) "America/North_Dakota/Center" , 0x0189BF }, - { (char*) "America/North_Dakota/New_Salem" , 0x018DBE }, - { (char*) "America/Nuuk" , 0x0191C3 }, - { (char*) "America/Ojinaga" , 0x0195A5 }, - { (char*) "America/Panama" , 0x01989B }, - { (char*) "America/Pangnirtung" , 0x01993C }, - { (char*) "America/Paramaribo" , 0x019C9F }, - { (char*) "America/Phoenix" , 0x019D66 }, - { (char*) "America/Port-au-Prince" , 0x019E7A }, - { (char*) "America/Port_of_Spain" , 0x01A0BB }, - { (char*) "America/Porto_Acre" , 0x01A149 }, - { (char*) "America/Porto_Velho" , 0x01A2F7 }, - { (char*) "America/Puerto_Rico" , 0x01A495 }, - { (char*) "America/Punta_Arenas" , 0x01A552 }, - { (char*) "America/Rainy_River" , 0x01AA34 }, - { (char*) "America/Rankin_Inlet" , 0x01AF4E }, - { (char*) "America/Recife" , 0x01B297 }, - { (char*) "America/Regina" , 0x01B491 }, - { (char*) "America/Resolute" , 0x01B730 }, - { (char*) "America/Rio_Branco" , 0x01BA7A }, - { (char*) "America/Rosario" , 0x01BC2C }, - { (char*) "America/Santa_Isabel" , 0x01BEFC }, - { (char*) "America/Santarem" , 0x01C33F }, - { (char*) "America/Santiago" , 0x01C4EF }, - { (char*) "America/Santo_Domingo" , 0x01CA52 }, - { (char*) "America/Sao_Paulo" , 0x01CB9B }, - { (char*) "America/Scoresbysund" , 0x01CF95 }, - { (char*) "America/Shiprock" , 0x01D396 }, - { (char*) "America/Sitka" , 0x01D7B4 }, - { (char*) "America/St_Barthelemy" , 0x01DB8F }, - { (char*) "America/St_Johns" , 0x01DC4C }, - { (char*) "America/St_Kitts" , 0x01E3C9 }, - { (char*) "America/St_Lucia" , 0x01E457 }, - { (char*) "America/St_Thomas" , 0x01E4F8 }, - { (char*) "America/St_Vincent" , 0x01E586 }, - { (char*) "America/Swift_Current" , 0x01E627 }, - { (char*) "America/Tegucigalpa" , 0x01E7B5 }, - { (char*) "America/Thule" , 0x01E883 }, - { (char*) "America/Thunder_Bay" , 0x01EA64 }, - { (char*) "America/Tijuana" , 0x01F125 }, - { (char*) "America/Toronto" , 0x01F577 }, - { (char*) "America/Tortola" , 0x01FC56 }, - { (char*) "America/Vancouver" , 0x01FCE4 }, - { (char*) "America/Virgin" , 0x02023B }, - { (char*) "America/Whitehorse" , 0x0202F8 }, - { (char*) "America/Winnipeg" , 0x02071B }, - { (char*) "America/Yakutat" , 0x020C52 }, - { (char*) "America/Yellowknife" , 0x021020 }, - { (char*) "Antarctica/Casey" , 0x0213F6 }, - { (char*) "Antarctica/Davis" , 0x021526 }, - { (char*) "Antarctica/DumontDUrville" , 0x0215FC }, - { (char*) "Antarctica/Macquarie" , 0x0216B0 }, - { (char*) "Antarctica/Mawson" , 0x021A9C }, - { (char*) "Antarctica/McMurdo" , 0x021B46 }, - { (char*) "Antarctica/Palmer" , 0x021E78 }, - { (char*) "Antarctica/Rothera" , 0x022201 }, - { (char*) "Antarctica/South_Pole" , 0x022298 }, - { (char*) "Antarctica/Syowa" , 0x0226B7 }, - { (char*) "Antarctica/Troll" , 0x02274D }, - { (char*) "Antarctica/Vostok" , 0x0227FC }, - { (char*) "Arctic/Longyearbyen" , 0x0228B8 }, - { (char*) "Asia/Aden" , 0x022B85 }, - { (char*) "Asia/Almaty" , 0x022C16 }, - { (char*) "Asia/Amman" , 0x022E9E }, - { (char*) "Asia/Anadyr" , 0x02324A }, - { (char*) "Asia/Aqtau" , 0x023550 }, - { (char*) "Asia/Aqtobe" , 0x0237CF }, - { (char*) "Asia/Ashgabat" , 0x023A4F }, - { (char*) "Asia/Ashkhabad" , 0x023BD2 }, - { (char*) "Asia/Atyrau" , 0x023D55 }, - { (char*) "Asia/Baghdad" , 0x023FDE }, - { (char*) "Asia/Bahrain" , 0x024260 }, - { (char*) "Asia/Baku" , 0x024319 }, - { (char*) "Asia/Bangkok" , 0x02460D }, - { (char*) "Asia/Barnaul" , 0x0246B1 }, - { (char*) "Asia/Beirut" , 0x0249BC }, - { (char*) "Asia/Bishkek" , 0x024CA4 }, - { (char*) "Asia/Brunei" , 0x024F1A }, - { (char*) "Asia/Calcutta" , 0x024FC0 }, - { (char*) "Asia/Chita" , 0x0250A8 }, - { (char*) "Asia/Choibalsan" , 0x0253B6 }, - { (char*) "Asia/Chongqing" , 0x025614 }, - { (char*) "Asia/Chungking" , 0x0257A9 }, - { (char*) "Asia/Colombo" , 0x02593E }, - { (char*) "Asia/Dacca" , 0x025A41 }, - { (char*) "Asia/Damascus" , 0x025B34 }, - { (char*) "Asia/Dhaka" , 0x026012 }, - { (char*) "Asia/Dili" , 0x026105 }, - { (char*) "Asia/Dubai" , 0x0261BB }, - { (char*) "Asia/Dushanbe" , 0x02624C }, - { (char*) "Asia/Famagusta" , 0x0263C6 }, - { (char*) "Asia/Gaza" , 0x02678D }, - { (char*) "Asia/Harbin" , 0x027329 }, - { (char*) "Asia/Hebron" , 0x0274BE }, - { (char*) "Asia/Ho_Chi_Minh" , 0x02806B }, - { (char*) "Asia/Hong_Kong" , 0x028163 }, - { (char*) "Asia/Hovd" , 0x028476 }, - { (char*) "Asia/Irkutsk" , 0x0286EA }, - { (char*) "Asia/Istanbul" , 0x028A08 }, - { (char*) "Asia/Jakarta" , 0x028EC4 }, - { (char*) "Asia/Jayapura" , 0x028FD5 }, - { (char*) "Asia/Jerusalem" , 0x0290C2 }, - { (char*) "Asia/Kabul" , 0x029500 }, - { (char*) "Asia/Kamchatka" , 0x0295AB }, - { (char*) "Asia/Karachi" , 0x0298A0 }, - { (char*) "Asia/Kashgar" , 0x0299B6 }, - { (char*) "Asia/Kathmandu" , 0x029A47 }, - { (char*) "Asia/Katmandu" , 0x029AF4 }, - { (char*) "Asia/Khandyga" , 0x029BA1 }, - { (char*) "Asia/Kolkata" , 0x029ED2 }, - { (char*) "Asia/Krasnoyarsk" , 0x029FBA }, - { (char*) "Asia/Kuala_Lumpur" , 0x02A2C4 }, - { (char*) "Asia/Kuching" , 0x02A3E4 }, - { (char*) "Asia/Kuwait" , 0x02A53E }, - { (char*) "Asia/Macao" , 0x02A5CF }, - { (char*) "Asia/Macau" , 0x02A8F2 }, - { (char*) "Asia/Magadan" , 0x02AC15 }, - { (char*) "Asia/Makassar" , 0x02AF20 }, - { (char*) "Asia/Manila" , 0x02B033 }, - { (char*) "Asia/Muscat" , 0x02B151 }, - { (char*) "Asia/Nicosia" , 0x02B1E2 }, - { (char*) "Asia/Novokuznetsk" , 0x02B451 }, - { (char*) "Asia/Novosibirsk" , 0x02B744 }, - { (char*) "Asia/Omsk" , 0x02BA55 }, - { (char*) "Asia/Oral" , 0x02BD53 }, - { (char*) "Asia/Phnom_Penh" , 0x02BFDF }, - { (char*) "Asia/Pontianak" , 0x02C0B3 }, - { (char*) "Asia/Pyongyang" , 0x02C1CC }, - { (char*) "Asia/Qatar" , 0x02C28F }, - { (char*) "Asia/Qostanay" , 0x02C333 }, - { (char*) "Asia/Qyzylorda" , 0x02C5C9 }, - { (char*) "Asia/Rangoon" , 0x02C862 }, - { (char*) "Asia/Riyadh" , 0x02C929 }, - { (char*) "Asia/Saigon" , 0x02C9BA }, - { (char*) "Asia/Sakhalin" , 0x02CAB2 }, - { (char*) "Asia/Samarkand" , 0x02CDC9 }, - { (char*) "Asia/Seoul" , 0x02CF54 }, - { (char*) "Asia/Shanghai" , 0x02D0FF }, - { (char*) "Asia/Singapore" , 0x02D2A0 }, - { (char*) "Asia/Srednekolymsk" , 0x02D3AC }, - { (char*) "Asia/Taipei" , 0x02D6BC }, - { (char*) "Asia/Tashkent" , 0x02D8C7 }, - { (char*) "Asia/Tbilisi" , 0x02DA52 }, - { (char*) "Asia/Tehran" , 0x02DCD3 }, - { (char*) "Asia/Tel_Aviv" , 0x02E00B }, - { (char*) "Asia/Thimbu" , 0x02E449 }, - { (char*) "Asia/Thimphu" , 0x02E4EF }, - { (char*) "Asia/Tokyo" , 0x02E595 }, - { (char*) "Asia/Tomsk" , 0x02E676 }, - { (char*) "Asia/Ujung_Pandang" , 0x02E981 }, - { (char*) "Asia/Ulaanbaatar" , 0x02EA4B }, - { (char*) "Asia/Ulan_Bator" , 0x02ECB9 }, - { (char*) "Asia/Urumqi" , 0x02EF17 }, - { (char*) "Asia/Ust-Nera" , 0x02EFB5 }, - { (char*) "Asia/Vientiane" , 0x02F2D8 }, - { (char*) "Asia/Vladivostok" , 0x02F3BE }, - { (char*) "Asia/Yakutsk" , 0x02F6C3 }, - { (char*) "Asia/Yangon" , 0x02F9C7 }, - { (char*) "Asia/Yekaterinburg" , 0x02FA8E }, - { (char*) "Asia/Yerevan" , 0x02FDA0 }, - { (char*) "Atlantic/Azores" , 0x030070 }, - { (char*) "Atlantic/Bermuda" , 0x0305FB }, - { (char*) "Atlantic/Canary" , 0x030A07 }, - { (char*) "Atlantic/Cape_Verde" , 0x030BFF }, - { (char*) "Atlantic/Faeroe" , 0x030CBA }, - { (char*) "Atlantic/Faroe" , 0x030E7F }, - { (char*) "Atlantic/Jan_Mayen" , 0x031044 }, - { (char*) "Atlantic/Madeira" , 0x031311 }, - { (char*) "Atlantic/Reykjavik" , 0x031888 }, - { (char*) "Atlantic/South_Georgia" , 0x031B85 }, - { (char*) "Atlantic/St_Helena" , 0x031C15 }, - { (char*) "Atlantic/Stanley" , 0x031CB6 }, - { (char*) "Australia/ACT" , 0x031FD7 }, - { (char*) "Australia/Adelaide" , 0x03236B }, - { (char*) "Australia/Brisbane" , 0x03271F }, - { (char*) "Australia/Broken_Hill" , 0x032863 }, - { (char*) "Australia/Canberra" , 0x032C38 }, - { (char*) "Australia/Currie" , 0x032FCC }, - { (char*) "Australia/Darwin" , 0x0333C3 }, - { (char*) "Australia/Eucla" , 0x0334CB }, - { (char*) "Australia/Hobart" , 0x03362A }, - { (char*) "Australia/LHI" , 0x033A29 }, - { (char*) "Australia/Lindeman" , 0x033CE9 }, - { (char*) "Australia/Lord_Howe" , 0x033E59 }, - { (char*) "Australia/Melbourne" , 0x034129 }, - { (char*) "Australia/North" , 0x0344C5 }, - { (char*) "Australia/NSW" , 0x0345BB }, - { (char*) "Australia/Perth" , 0x03494F }, - { (char*) "Australia/Queensland" , 0x034AAB }, - { (char*) "Australia/South" , 0x034BD8 }, - { (char*) "Australia/Sydney" , 0x034F7D }, - { (char*) "Australia/Tasmania" , 0x03532D }, - { (char*) "Australia/Victoria" , 0x035724 }, - { (char*) "Australia/West" , 0x035AB8 }, - { (char*) "Australia/Yancowinna" , 0x035BF6 }, - { (char*) "Brazil/Acre" , 0x035FAF }, - { (char*) "Brazil/DeNoronha" , 0x03615D }, - { (char*) "Brazil/East" , 0x03634D }, - { (char*) "Brazil/West" , 0x036711 }, - { (char*) "Canada/Atlantic" , 0x0368B9 }, - { (char*) "Canada/Central" , 0x036F4D }, - { (char*) "Canada/Eastern" , 0x037467 }, - { (char*) "Canada/Mountain" , 0x037B28 }, - { (char*) "Canada/Newfoundland" , 0x037EFE }, - { (char*) "Canada/Pacific" , 0x038660 }, - { (char*) "Canada/Saskatchewan" , 0x038B9E }, - { (char*) "Canada/Yukon" , 0x038E28 }, - { (char*) "CET" , 0x039239 }, - { (char*) "Chile/Continental" , 0x039694 }, - { (char*) "Chile/EasterIsland" , 0x039BEA }, - { (char*) "CST6CDT" , 0x03A08C }, - { (char*) "Cuba" , 0x03A772 }, - { (char*) "EET" , 0x03ABDB }, - { (char*) "Egypt" , 0x03AE91 }, - { (char*) "Eire" , 0x03B3BA }, - { (char*) "EST" , 0x03B99E }, - { (char*) "EST5EDT" , 0x03BA3F }, - { (char*) "Etc/GMT" , 0x03C11B }, - { (char*) "Etc/GMT+0" , 0x03C196 }, - { (char*) "Etc/GMT+1" , 0x03C211 }, - { (char*) "Etc/GMT+10" , 0x03C28E }, - { (char*) "Etc/GMT+11" , 0x03C30C }, - { (char*) "Etc/GMT+12" , 0x03C38A }, - { (char*) "Etc/GMT+2" , 0x03C408 }, - { (char*) "Etc/GMT+3" , 0x03C485 }, - { (char*) "Etc/GMT+4" , 0x03C502 }, - { (char*) "Etc/GMT+5" , 0x03C57F }, - { (char*) "Etc/GMT+6" , 0x03C5FC }, - { (char*) "Etc/GMT+7" , 0x03C679 }, - { (char*) "Etc/GMT+8" , 0x03C6F6 }, - { (char*) "Etc/GMT+9" , 0x03C773 }, - { (char*) "Etc/GMT-0" , 0x03C7F0 }, - { (char*) "Etc/GMT-1" , 0x03C86B }, - { (char*) "Etc/GMT-10" , 0x03C8E9 }, - { (char*) "Etc/GMT-11" , 0x03C968 }, - { (char*) "Etc/GMT-12" , 0x03C9E7 }, - { (char*) "Etc/GMT-13" , 0x03CA66 }, - { (char*) "Etc/GMT-14" , 0x03CAE5 }, - { (char*) "Etc/GMT-2" , 0x03CB64 }, - { (char*) "Etc/GMT-3" , 0x03CBE2 }, - { (char*) "Etc/GMT-4" , 0x03CC60 }, - { (char*) "Etc/GMT-5" , 0x03CCDE }, - { (char*) "Etc/GMT-6" , 0x03CD5C }, - { (char*) "Etc/GMT-7" , 0x03CDDA }, - { (char*) "Etc/GMT-8" , 0x03CE58 }, - { (char*) "Etc/GMT-9" , 0x03CED6 }, - { (char*) "Etc/GMT0" , 0x03CF54 }, - { (char*) "Etc/Greenwich" , 0x03CFCF }, - { (char*) "Etc/UCT" , 0x03D04A }, - { (char*) "Etc/Universal" , 0x03D0C5 }, - { (char*) "Etc/UTC" , 0x03D140 }, - { (char*) "Etc/Zulu" , 0x03D1BB }, - { (char*) "Europe/Amsterdam" , 0x03D236 }, - { (char*) "Europe/Andorra" , 0x03D671 }, - { (char*) "Europe/Astrakhan" , 0x03D802 }, - { (char*) "Europe/Athens" , 0x03DAF6 }, - { (char*) "Europe/Belfast" , 0x03DDAC }, - { (char*) "Europe/Belgrade" , 0x03E3F7 }, - { (char*) "Europe/Berlin" , 0x03E5E1 }, - { (char*) "Europe/Bratislava" , 0x03E8BD }, - { (char*) "Europe/Brussels" , 0x03EB9C }, - { (char*) "Europe/Bucharest" , 0x03EFF7 }, - { (char*) "Europe/Budapest" , 0x03F298 }, - { (char*) "Europe/Busingen" , 0x03F5A2 }, - { (char*) "Europe/Chisinau" , 0x03F7A7 }, - { (char*) "Europe/Copenhagen" , 0x03FAA6 }, - { (char*) "Europe/Dublin" , 0x03FD21 }, - { (char*) "Europe/Gibraltar" , 0x040305 }, - { (char*) "Europe/Guernsey" , 0x0407D5 }, - { (char*) "Europe/Helsinki" , 0x040E2C }, - { (char*) "Europe/Isle_of_Man" , 0x041019 }, - { (char*) "Europe/Istanbul" , 0x041664 }, - { (char*) "Europe/Jersey" , 0x041B20 }, - { (char*) "Europe/Kaliningrad" , 0x042177 }, - { (char*) "Europe/Kiev" , 0x04251F }, - { (char*) "Europe/Kirov" , 0x042759 }, - { (char*) "Europe/Kyiv" , 0x042A52 }, - { (char*) "Europe/Lisbon" , 0x042C9B }, - { (char*) "Europe/Ljubljana" , 0x043271 }, - { (char*) "Europe/London" , 0x04345B }, - { (char*) "Europe/Luxembourg" , 0x043AA6 }, - { (char*) "Europe/Madrid" , 0x043EF1 }, - { (char*) "Europe/Malta" , 0x04428E }, - { (char*) "Europe/Mariehamn" , 0x04463A }, - { (char*) "Europe/Minsk" , 0x044827 }, - { (char*) "Europe/Monaco" , 0x044B5B }, - { (char*) "Europe/Moscow" , 0x044FC1 }, - { (char*) "Europe/Nicosia" , 0x04536D }, - { (char*) "Europe/Oslo" , 0x0455CE }, - { (char*) "Europe/Paris" , 0x04587E }, - { (char*) "Europe/Podgorica" , 0x045CDB }, - { (char*) "Europe/Prague" , 0x045EC5 }, - { (char*) "Europe/Riga" , 0x0461A4 }, - { (char*) "Europe/Rome" , 0x046466 }, - { (char*) "Europe/Samara" , 0x046825 }, - { (char*) "Europe/San_Marino" , 0x046B26 }, - { (char*) "Europe/Sarajevo" , 0x046EE5 }, - { (char*) "Europe/Saratov" , 0x0470CF }, - { (char*) "Europe/Simferopol" , 0x0473C1 }, - { (char*) "Europe/Skopje" , 0x047734 }, - { (char*) "Europe/Sofia" , 0x04791E }, - { (char*) "Europe/Stockholm" , 0x047B7A }, - { (char*) "Europe/Tallinn" , 0x047D77 }, - { (char*) "Europe/Tirane" , 0x048026 }, - { (char*) "Europe/Tiraspol" , 0x04828E }, - { (char*) "Europe/Ulyanovsk" , 0x04858D }, - { (char*) "Europe/Uzhgorod" , 0x0488A3 }, - { (char*) "Europe/Vaduz" , 0x048ADD }, - { (char*) "Europe/Vatican" , 0x048CC7 }, - { (char*) "Europe/Vienna" , 0x049086 }, - { (char*) "Europe/Vilnius" , 0x049324 }, - { (char*) "Europe/Volgograd" , 0x0495D4 }, - { (char*) "Europe/Warsaw" , 0x0498E3 }, - { (char*) "Europe/Zagreb" , 0x049C8A }, - { (char*) "Europe/Zaporozhye" , 0x049E74 }, - { (char*) "Europe/Zurich" , 0x04A0AE }, - { (char*) "Factory" , 0x04A2AB }, - { (char*) "GB" , 0x04A328 }, - { (char*) "GB-Eire" , 0x04A973 }, - { (char*) "GMT" , 0x04AFBE }, - { (char*) "GMT+0" , 0x04B039 }, - { (char*) "GMT-0" , 0x04B0B4 }, - { (char*) "GMT0" , 0x04B12F }, - { (char*) "Greenwich" , 0x04B1AA }, - { (char*) "Hongkong" , 0x04B225 }, - { (char*) "HST" , 0x04B538 }, - { (char*) "Iceland" , 0x04B621 }, - { (char*) "Indian/Antananarivo" , 0x04B6AF }, - { (char*) "Indian/Chagos" , 0x04B75B }, - { (char*) "Indian/Christmas" , 0x04B7FF }, - { (char*) "Indian/Cocos" , 0x04B890 }, - { (char*) "Indian/Comoro" , 0x04B928 }, - { (char*) "Indian/Kerguelen" , 0x04B9B7 }, - { (char*) "Indian/Mahe" , 0x04BA48 }, - { (char*) "Indian/Maldives" , 0x04BAD9 }, - { (char*) "Indian/Mauritius" , 0x04BB7D }, - { (char*) "Indian/Mayotte" , 0x04BC3C }, - { (char*) "Indian/Reunion" , 0x04BCCB }, - { (char*) "Iran" , 0x04BD5C }, - { (char*) "Israel" , 0x04C094 }, - { (char*) "Jamaica" , 0x04C4D2 }, - { (char*) "Japan" , 0x04C631 }, - { (char*) "Kwajalein" , 0x04C712 }, - { (char*) "Libya" , 0x04C7F9 }, - { (char*) "MET" , 0x04C9B4 }, - { (char*) "Mexico/BajaNorte" , 0x04CE0F }, - { (char*) "Mexico/BajaSur" , 0x04D252 }, - { (char*) "Mexico/General" , 0x04D510 }, - { (char*) "MST" , 0x04D821 }, - { (char*) "MST7MDT" , 0x04D91D }, - { (char*) "Navajo" , 0x04DD3B }, - { (char*) "NZ" , 0x04E159 }, - { (char*) "NZ-CHAT" , 0x04E578 }, - { (char*) "Pacific/Apia" , 0x04E8AC }, - { (char*) "Pacific/Auckland" , 0x04EA4F }, - { (char*) "Pacific/Bougainville" , 0x04EE81 }, - { (char*) "Pacific/Chatham" , 0x04EF62 }, - { (char*) "Pacific/Chuuk" , 0x04F2A5 }, - { (char*) "Pacific/Easter" , 0x04F383 }, - { (char*) "Pacific/Efate" , 0x04F832 }, - { (char*) "Pacific/Enderbury" , 0x04F994 }, - { (char*) "Pacific/Fakaofo" , 0x04FA4C }, - { (char*) "Pacific/Fiji" , 0x04FAF1 }, - { (char*) "Pacific/Funafuti" , 0x04FC89 }, - { (char*) "Pacific/Galapagos" , 0x04FD1B }, - { (char*) "Pacific/Gambier" , 0x04FDE7 }, - { (char*) "Pacific/Guadalcanal" , 0x04FE86 }, - { (char*) "Pacific/Guam" , 0x04FF18 }, - { (char*) "Pacific/Honolulu" , 0x050082 }, - { (char*) "Pacific/Johnston" , 0x050171 }, - { (char*) "Pacific/Kanton" , 0x05025A }, - { (char*) "Pacific/Kiritimati" , 0x050321 }, - { (char*) "Pacific/Kosrae" , 0x0503E7 }, - { (char*) "Pacific/Kwajalein" , 0x0504EB }, - { (char*) "Pacific/Majuro" , 0x0505DB }, - { (char*) "Pacific/Marquesas" , 0x0506D9 }, - { (char*) "Pacific/Midway" , 0x050781 }, - { (char*) "Pacific/Nauru" , 0x050844 }, - { (char*) "Pacific/Niue" , 0x050907 }, - { (char*) "Pacific/Norfolk" , 0x0509AD }, - { (char*) "Pacific/Noumea" , 0x050AA6 }, - { (char*) "Pacific/Pago_Pago" , 0x050B78 }, - { (char*) "Pacific/Palau" , 0x050C16 }, - { (char*) "Pacific/Pitcairn" , 0x050CB6 }, - { (char*) "Pacific/Pohnpei" , 0x050D5B }, - { (char*) "Pacific/Ponape" , 0x050E4B }, - { (char*) "Pacific/Port_Moresby" , 0x050EDD }, - { (char*) "Pacific/Rarotonga" , 0x050F9B }, - { (char*) "Pacific/Saipan" , 0x05113D }, - { (char*) "Pacific/Samoa" , 0x05129E }, - { (char*) "Pacific/Tahiti" , 0x05133C }, - { (char*) "Pacific/Tarawa" , 0x0513DC }, - { (char*) "Pacific/Tongatapu" , 0x05147D }, - { (char*) "Pacific/Truk" , 0x051576 }, - { (char*) "Pacific/Wake" , 0x05161C }, - { (char*) "Pacific/Wallis" , 0x0516B9 }, - { (char*) "Pacific/Yap" , 0x05174B }, - { (char*) "Poland" , 0x0517F1 }, - { (char*) "Portugal" , 0x051B98 }, - { (char*) "PRC" , 0x05215B }, - { (char*) "PST8PDT" , 0x0522F0 }, - { (char*) "ROC" , 0x05280A }, - { (char*) "ROK" , 0x052A15 }, - { (char*) "Singapore" , 0x052BC0 }, - { (char*) "Turkey" , 0x052CCC }, - { (char*) "UCT" , 0x053188 }, - { (char*) "Universal" , 0x053203 }, - { (char*) "US/Alaska" , 0x05327E }, - { (char*) "US/Aleutian" , 0x05365B }, - { (char*) "US/Arizona" , 0x053A30 }, - { (char*) "US/Central" , 0x053B2C }, - { (char*) "US/East-Indiana" , 0x054212 }, - { (char*) "US/Eastern" , 0x054431 }, - { (char*) "US/Hawaii" , 0x054B0D }, - { (char*) "US/Indiana-Starke" , 0x054BF6 }, - { (char*) "US/Michigan" , 0x054FFA }, - { (char*) "US/Mountain" , 0x055389 }, - { (char*) "US/Pacific" , 0x0557A7 }, - { (char*) "US/Samoa" , 0x055CC1 }, - { (char*) "UTC" , 0x055D5F }, - { (char*) "W-SU" , 0x055DDA }, - { (char*) "WET" , 0x056172 }, - { (char*) "Zulu" , 0x056735 }, + { (char*) "America/Coyhaique" , 0x00B238 }, + { (char*) "America/Creston" , 0x00B7A2 }, + { (char*) "America/Cuiaba" , 0x00B85E }, + { (char*) "America/Curacao" , 0x00BC1B }, + { (char*) "America/Danmarkshavn" , 0x00BCBE }, + { (char*) "America/Dawson" , 0x00BEA3 }, + { (char*) "America/Dawson_Creek" , 0x00C2C6 }, + { (char*) "America/Denver" , 0x00C59D }, + { (char*) "America/Detroit" , 0x00C9D0 }, + { (char*) "America/Dominica" , 0x00CD78 }, + { (char*) "America/Edmonton" , 0x00CE06 }, + { (char*) "America/Eirunepe" , 0x00D1FE }, + { (char*) "America/El_Salvador" , 0x00D3CD }, + { (char*) "America/Ensenada" , 0x00D489 }, + { (char*) "America/Fort_Nelson" , 0x00D8CC }, + { (char*) "America/Fort_Wayne" , 0x00DE94 }, + { (char*) "America/Fortaleza" , 0x00E0B3 }, + { (char*) "America/Glace_Bay" , 0x00E2C9 }, + { (char*) "America/Godthab" , 0x00E660 }, + { (char*) "America/Goose_Bay" , 0x00EA31 }, + { (char*) "America/Grand_Turk" , 0x00F089 }, + { (char*) "America/Grenada" , 0x00F3EA }, + { (char*) "America/Guadeloupe" , 0x00F478 }, + { (char*) "America/Guatemala" , 0x00F506 }, + { (char*) "America/Guayaquil" , 0x00F5E6 }, + { (char*) "America/Guyana" , 0x00F6B7 }, + { (char*) "America/Halifax" , 0x00F778 }, + { (char*) "America/Havana" , 0x00FE2A }, + { (char*) "America/Hermosillo" , 0x010293 }, + { (char*) "America/Indiana/Indianapolis" , 0x0103A7 }, + { (char*) "America/Indiana/Knox" , 0x0105DF }, + { (char*) "America/Indiana/Marengo" , 0x0109F8 }, + { (char*) "America/Indiana/Petersburg" , 0x010C52 }, + { (char*) "America/Indiana/Tell_City" , 0x010F1C }, + { (char*) "America/Indiana/Vevay" , 0x011146 }, + { (char*) "America/Indiana/Vincennes" , 0x0112DD }, + { (char*) "America/Indiana/Winamac" , 0x011533 }, + { (char*) "America/Indianapolis" , 0x0117B0 }, + { (char*) "America/Inuvik" , 0x0119CF }, + { (char*) "America/Iqaluit" , 0x011D20 }, + { (char*) "America/Jamaica" , 0x01209C }, + { (char*) "America/Jujuy" , 0x0121FB }, + { (char*) "America/Juneau" , 0x0124B9 }, + { (char*) "America/Kentucky/Louisville" , 0x01289F }, + { (char*) "America/Kentucky/Monticello" , 0x012DA3 }, + { (char*) "America/Knox_IN" , 0x01318F }, + { (char*) "America/Kralendijk" , 0x013593 }, + { (char*) "America/La_Paz" , 0x013650 }, + { (char*) "America/Lima" , 0x013706 }, + { (char*) "America/Los_Angeles" , 0x01382D }, + { (char*) "America/Louisville" , 0x013D4E }, + { (char*) "America/Lower_Princes" , 0x014234 }, + { (char*) "America/Maceio" , 0x0142F1 }, + { (char*) "America/Managua" , 0x014503 }, + { (char*) "America/Manaus" , 0x014636 }, + { (char*) "America/Marigot" , 0x0147ED }, + { (char*) "America/Martinique" , 0x0148AA }, + { (char*) "America/Matamoros" , 0x014968 }, + { (char*) "America/Mazatlan" , 0x014B55 }, + { (char*) "America/Mendoza" , 0x014E45 }, + { (char*) "America/Menominee" , 0x015115 }, + { (char*) "America/Merida" , 0x0154D5 }, + { (char*) "America/Metlakatla" , 0x015780 }, + { (char*) "America/Mexico_City" , 0x0159ED }, + { (char*) "America/Miquelon" , 0x015D0C }, + { (char*) "America/Moncton" , 0x015F3E }, + { (char*) "America/Monterrey" , 0x016537 }, + { (char*) "America/Montevideo" , 0x01683E }, + { (char*) "America/Montreal" , 0x016C13 }, + { (char*) "America/Montserrat" , 0x0172D4 }, + { (char*) "America/Nassau" , 0x017362 }, + { (char*) "America/New_York" , 0x01775C }, + { (char*) "America/Nipigon" , 0x017E4C }, + { (char*) "America/Nome" , 0x01850D }, + { (char*) "America/Noronha" , 0x0188F5 }, + { (char*) "America/North_Dakota/Beulah" , 0x018AF5 }, + { (char*) "America/North_Dakota/Center" , 0x018F29 }, + { (char*) "America/North_Dakota/New_Salem" , 0x019328 }, + { (char*) "America/Nuuk" , 0x01972D }, + { (char*) "America/Ojinaga" , 0x019B0F }, + { (char*) "America/Panama" , 0x019E05 }, + { (char*) "America/Pangnirtung" , 0x019EA6 }, + { (char*) "America/Paramaribo" , 0x01A209 }, + { (char*) "America/Phoenix" , 0x01A2D0 }, + { (char*) "America/Port-au-Prince" , 0x01A3E4 }, + { (char*) "America/Port_of_Spain" , 0x01A625 }, + { (char*) "America/Porto_Acre" , 0x01A6B3 }, + { (char*) "America/Porto_Velho" , 0x01A861 }, + { (char*) "America/Puerto_Rico" , 0x01A9FF }, + { (char*) "America/Punta_Arenas" , 0x01AABC }, + { (char*) "America/Rainy_River" , 0x01AF9B }, + { (char*) "America/Rankin_Inlet" , 0x01B4B5 }, + { (char*) "America/Recife" , 0x01B7FE }, + { (char*) "America/Regina" , 0x01B9F8 }, + { (char*) "America/Resolute" , 0x01BC97 }, + { (char*) "America/Rio_Branco" , 0x01BFE1 }, + { (char*) "America/Rosario" , 0x01C193 }, + { (char*) "America/Santa_Isabel" , 0x01C463 }, + { (char*) "America/Santarem" , 0x01C8A6 }, + { (char*) "America/Santiago" , 0x01CA56 }, + { (char*) "America/Santo_Domingo" , 0x01CFB9 }, + { (char*) "America/Sao_Paulo" , 0x01D102 }, + { (char*) "America/Scoresbysund" , 0x01D4FC }, + { (char*) "America/Shiprock" , 0x01D8FD }, + { (char*) "America/Sitka" , 0x01DD1B }, + { (char*) "America/St_Barthelemy" , 0x01E0F6 }, + { (char*) "America/St_Johns" , 0x01E1B3 }, + { (char*) "America/St_Kitts" , 0x01E930 }, + { (char*) "America/St_Lucia" , 0x01E9BE }, + { (char*) "America/St_Thomas" , 0x01EA5F }, + { (char*) "America/St_Vincent" , 0x01EAED }, + { (char*) "America/Swift_Current" , 0x01EB8E }, + { (char*) "America/Tegucigalpa" , 0x01ED1C }, + { (char*) "America/Thule" , 0x01EDEA }, + { (char*) "America/Thunder_Bay" , 0x01EFCB }, + { (char*) "America/Tijuana" , 0x01F68C }, + { (char*) "America/Toronto" , 0x01FADE }, + { (char*) "America/Tortola" , 0x0201BD }, + { (char*) "America/Vancouver" , 0x02024B }, + { (char*) "America/Virgin" , 0x0207A2 }, + { (char*) "America/Whitehorse" , 0x02085F }, + { (char*) "America/Winnipeg" , 0x020C82 }, + { (char*) "America/Yakutat" , 0x0211B9 }, + { (char*) "America/Yellowknife" , 0x021587 }, + { (char*) "Antarctica/Casey" , 0x02195D }, + { (char*) "Antarctica/Davis" , 0x021A8D }, + { (char*) "Antarctica/DumontDUrville" , 0x021B63 }, + { (char*) "Antarctica/Macquarie" , 0x021C17 }, + { (char*) "Antarctica/Mawson" , 0x022003 }, + { (char*) "Antarctica/McMurdo" , 0x0220AD }, + { (char*) "Antarctica/Palmer" , 0x0223DF }, + { (char*) "Antarctica/Rothera" , 0x022768 }, + { (char*) "Antarctica/South_Pole" , 0x0227FF }, + { (char*) "Antarctica/Syowa" , 0x022C1E }, + { (char*) "Antarctica/Troll" , 0x022CB4 }, + { (char*) "Antarctica/Vostok" , 0x022D63 }, + { (char*) "Arctic/Longyearbyen" , 0x022E1F }, + { (char*) "Asia/Aden" , 0x0230EC }, + { (char*) "Asia/Almaty" , 0x02317D }, + { (char*) "Asia/Amman" , 0x023405 }, + { (char*) "Asia/Anadyr" , 0x0237B1 }, + { (char*) "Asia/Aqtau" , 0x023AB7 }, + { (char*) "Asia/Aqtobe" , 0x023D36 }, + { (char*) "Asia/Ashgabat" , 0x023FB6 }, + { (char*) "Asia/Ashkhabad" , 0x024139 }, + { (char*) "Asia/Atyrau" , 0x0242BC }, + { (char*) "Asia/Baghdad" , 0x024545 }, + { (char*) "Asia/Bahrain" , 0x0247C7 }, + { (char*) "Asia/Baku" , 0x024880 }, + { (char*) "Asia/Bangkok" , 0x024B74 }, + { (char*) "Asia/Barnaul" , 0x024C18 }, + { (char*) "Asia/Beirut" , 0x024F23 }, + { (char*) "Asia/Bishkek" , 0x02520B }, + { (char*) "Asia/Brunei" , 0x025481 }, + { (char*) "Asia/Calcutta" , 0x025527 }, + { (char*) "Asia/Chita" , 0x02560F }, + { (char*) "Asia/Choibalsan" , 0x02591D }, + { (char*) "Asia/Chongqing" , 0x025B7B }, + { (char*) "Asia/Chungking" , 0x025D10 }, + { (char*) "Asia/Colombo" , 0x025EA5 }, + { (char*) "Asia/Dacca" , 0x025FA8 }, + { (char*) "Asia/Damascus" , 0x02609B }, + { (char*) "Asia/Dhaka" , 0x026579 }, + { (char*) "Asia/Dili" , 0x02666C }, + { (char*) "Asia/Dubai" , 0x026722 }, + { (char*) "Asia/Dushanbe" , 0x0267B3 }, + { (char*) "Asia/Famagusta" , 0x02692D }, + { (char*) "Asia/Gaza" , 0x026CF4 }, + { (char*) "Asia/Harbin" , 0x027890 }, + { (char*) "Asia/Hebron" , 0x027A25 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x0285D2 }, + { (char*) "Asia/Hong_Kong" , 0x0286CA }, + { (char*) "Asia/Hovd" , 0x0289DD }, + { (char*) "Asia/Irkutsk" , 0x028C51 }, + { (char*) "Asia/Istanbul" , 0x028F6F }, + { (char*) "Asia/Jakarta" , 0x02942B }, + { (char*) "Asia/Jayapura" , 0x02953C }, + { (char*) "Asia/Jerusalem" , 0x029629 }, + { (char*) "Asia/Kabul" , 0x029A67 }, + { (char*) "Asia/Kamchatka" , 0x029B12 }, + { (char*) "Asia/Karachi" , 0x029E07 }, + { (char*) "Asia/Kashgar" , 0x029F1D }, + { (char*) "Asia/Kathmandu" , 0x029FAE }, + { (char*) "Asia/Katmandu" , 0x02A05B }, + { (char*) "Asia/Khandyga" , 0x02A108 }, + { (char*) "Asia/Kolkata" , 0x02A439 }, + { (char*) "Asia/Krasnoyarsk" , 0x02A521 }, + { (char*) "Asia/Kuala_Lumpur" , 0x02A82B }, + { (char*) "Asia/Kuching" , 0x02A94B }, + { (char*) "Asia/Kuwait" , 0x02AAA5 }, + { (char*) "Asia/Macao" , 0x02AB36 }, + { (char*) "Asia/Macau" , 0x02AE59 }, + { (char*) "Asia/Magadan" , 0x02B17C }, + { (char*) "Asia/Makassar" , 0x02B487 }, + { (char*) "Asia/Manila" , 0x02B59A }, + { (char*) "Asia/Muscat" , 0x02B6B8 }, + { (char*) "Asia/Nicosia" , 0x02B749 }, + { (char*) "Asia/Novokuznetsk" , 0x02B9B8 }, + { (char*) "Asia/Novosibirsk" , 0x02BCAB }, + { (char*) "Asia/Omsk" , 0x02BFBC }, + { (char*) "Asia/Oral" , 0x02C2BA }, + { (char*) "Asia/Phnom_Penh" , 0x02C546 }, + { (char*) "Asia/Pontianak" , 0x02C61A }, + { (char*) "Asia/Pyongyang" , 0x02C733 }, + { (char*) "Asia/Qatar" , 0x02C7F6 }, + { (char*) "Asia/Qostanay" , 0x02C89A }, + { (char*) "Asia/Qyzylorda" , 0x02CB30 }, + { (char*) "Asia/Rangoon" , 0x02CDC9 }, + { (char*) "Asia/Riyadh" , 0x02CE90 }, + { (char*) "Asia/Saigon" , 0x02CF21 }, + { (char*) "Asia/Sakhalin" , 0x02D019 }, + { (char*) "Asia/Samarkand" , 0x02D330 }, + { (char*) "Asia/Seoul" , 0x02D4BB }, + { (char*) "Asia/Shanghai" , 0x02D666 }, + { (char*) "Asia/Singapore" , 0x02D807 }, + { (char*) "Asia/Srednekolymsk" , 0x02D913 }, + { (char*) "Asia/Taipei" , 0x02DC23 }, + { (char*) "Asia/Tashkent" , 0x02DE2E }, + { (char*) "Asia/Tbilisi" , 0x02DFB9 }, + { (char*) "Asia/Tehran" , 0x02E23A }, + { (char*) "Asia/Tel_Aviv" , 0x02E572 }, + { (char*) "Asia/Thimbu" , 0x02E9B0 }, + { (char*) "Asia/Thimphu" , 0x02EA56 }, + { (char*) "Asia/Tokyo" , 0x02EAFC }, + { (char*) "Asia/Tomsk" , 0x02EBDD }, + { (char*) "Asia/Ujung_Pandang" , 0x02EEE8 }, + { (char*) "Asia/Ulaanbaatar" , 0x02EFB2 }, + { (char*) "Asia/Ulan_Bator" , 0x02F220 }, + { (char*) "Asia/Urumqi" , 0x02F47E }, + { (char*) "Asia/Ust-Nera" , 0x02F51C }, + { (char*) "Asia/Vientiane" , 0x02F83F }, + { (char*) "Asia/Vladivostok" , 0x02F925 }, + { (char*) "Asia/Yakutsk" , 0x02FC2A }, + { (char*) "Asia/Yangon" , 0x02FF2E }, + { (char*) "Asia/Yekaterinburg" , 0x02FFF5 }, + { (char*) "Asia/Yerevan" , 0x030307 }, + { (char*) "Atlantic/Azores" , 0x0305D7 }, + { (char*) "Atlantic/Bermuda" , 0x030B62 }, + { (char*) "Atlantic/Canary" , 0x030F6E }, + { (char*) "Atlantic/Cape_Verde" , 0x031166 }, + { (char*) "Atlantic/Faeroe" , 0x031221 }, + { (char*) "Atlantic/Faroe" , 0x0313E6 }, + { (char*) "Atlantic/Jan_Mayen" , 0x0315AB }, + { (char*) "Atlantic/Madeira" , 0x031878 }, + { (char*) "Atlantic/Reykjavik" , 0x031DEF }, + { (char*) "Atlantic/South_Georgia" , 0x0320EC }, + { (char*) "Atlantic/St_Helena" , 0x03217C }, + { (char*) "Atlantic/Stanley" , 0x03221D }, + { (char*) "Australia/ACT" , 0x03253E }, + { (char*) "Australia/Adelaide" , 0x0328D2 }, + { (char*) "Australia/Brisbane" , 0x032C86 }, + { (char*) "Australia/Broken_Hill" , 0x032DCA }, + { (char*) "Australia/Canberra" , 0x03319F }, + { (char*) "Australia/Currie" , 0x033533 }, + { (char*) "Australia/Darwin" , 0x03392A }, + { (char*) "Australia/Eucla" , 0x033A32 }, + { (char*) "Australia/Hobart" , 0x033B91 }, + { (char*) "Australia/LHI" , 0x033F90 }, + { (char*) "Australia/Lindeman" , 0x034250 }, + { (char*) "Australia/Lord_Howe" , 0x0343C0 }, + { (char*) "Australia/Melbourne" , 0x034690 }, + { (char*) "Australia/North" , 0x034A2C }, + { (char*) "Australia/NSW" , 0x034B22 }, + { (char*) "Australia/Perth" , 0x034EB6 }, + { (char*) "Australia/Queensland" , 0x035012 }, + { (char*) "Australia/South" , 0x03513F }, + { (char*) "Australia/Sydney" , 0x0354E4 }, + { (char*) "Australia/Tasmania" , 0x035894 }, + { (char*) "Australia/Victoria" , 0x035C8B }, + { (char*) "Australia/West" , 0x03601F }, + { (char*) "Australia/Yancowinna" , 0x03615D }, + { (char*) "Brazil/Acre" , 0x036516 }, + { (char*) "Brazil/DeNoronha" , 0x0366C4 }, + { (char*) "Brazil/East" , 0x0368B4 }, + { (char*) "Brazil/West" , 0x036C78 }, + { (char*) "Canada/Atlantic" , 0x036E20 }, + { (char*) "Canada/Central" , 0x0374B4 }, + { (char*) "Canada/Eastern" , 0x0379CE }, + { (char*) "Canada/Mountain" , 0x03808F }, + { (char*) "Canada/Newfoundland" , 0x038465 }, + { (char*) "Canada/Pacific" , 0x038BC7 }, + { (char*) "Canada/Saskatchewan" , 0x039105 }, + { (char*) "Canada/Yukon" , 0x03938F }, + { (char*) "CET" , 0x0397A0 }, + { (char*) "Chile/Continental" , 0x039BFB }, + { (char*) "Chile/EasterIsland" , 0x03A151 }, + { (char*) "CST6CDT" , 0x03A5F3 }, + { (char*) "Cuba" , 0x03ACD9 }, + { (char*) "EET" , 0x03B142 }, + { (char*) "Egypt" , 0x03B3F8 }, + { (char*) "Eire" , 0x03B921 }, + { (char*) "EST" , 0x03BF05 }, + { (char*) "EST5EDT" , 0x03BFA6 }, + { (char*) "Etc/GMT" , 0x03C682 }, + { (char*) "Etc/GMT+0" , 0x03C6FD }, + { (char*) "Etc/GMT+1" , 0x03C778 }, + { (char*) "Etc/GMT+10" , 0x03C7F5 }, + { (char*) "Etc/GMT+11" , 0x03C873 }, + { (char*) "Etc/GMT+12" , 0x03C8F1 }, + { (char*) "Etc/GMT+2" , 0x03C96F }, + { (char*) "Etc/GMT+3" , 0x03C9EC }, + { (char*) "Etc/GMT+4" , 0x03CA69 }, + { (char*) "Etc/GMT+5" , 0x03CAE6 }, + { (char*) "Etc/GMT+6" , 0x03CB63 }, + { (char*) "Etc/GMT+7" , 0x03CBE0 }, + { (char*) "Etc/GMT+8" , 0x03CC5D }, + { (char*) "Etc/GMT+9" , 0x03CCDA }, + { (char*) "Etc/GMT-0" , 0x03CD57 }, + { (char*) "Etc/GMT-1" , 0x03CDD2 }, + { (char*) "Etc/GMT-10" , 0x03CE50 }, + { (char*) "Etc/GMT-11" , 0x03CECF }, + { (char*) "Etc/GMT-12" , 0x03CF4E }, + { (char*) "Etc/GMT-13" , 0x03CFCD }, + { (char*) "Etc/GMT-14" , 0x03D04C }, + { (char*) "Etc/GMT-2" , 0x03D0CB }, + { (char*) "Etc/GMT-3" , 0x03D149 }, + { (char*) "Etc/GMT-4" , 0x03D1C7 }, + { (char*) "Etc/GMT-5" , 0x03D245 }, + { (char*) "Etc/GMT-6" , 0x03D2C3 }, + { (char*) "Etc/GMT-7" , 0x03D341 }, + { (char*) "Etc/GMT-8" , 0x03D3BF }, + { (char*) "Etc/GMT-9" , 0x03D43D }, + { (char*) "Etc/GMT0" , 0x03D4BB }, + { (char*) "Etc/Greenwich" , 0x03D536 }, + { (char*) "Etc/UCT" , 0x03D5B1 }, + { (char*) "Etc/Universal" , 0x03D62C }, + { (char*) "Etc/UTC" , 0x03D6A7 }, + { (char*) "Etc/Zulu" , 0x03D722 }, + { (char*) "Europe/Amsterdam" , 0x03D79D }, + { (char*) "Europe/Andorra" , 0x03DBD8 }, + { (char*) "Europe/Astrakhan" , 0x03DD69 }, + { (char*) "Europe/Athens" , 0x03E05D }, + { (char*) "Europe/Belfast" , 0x03E313 }, + { (char*) "Europe/Belgrade" , 0x03E95E }, + { (char*) "Europe/Berlin" , 0x03EB48 }, + { (char*) "Europe/Bratislava" , 0x03EE24 }, + { (char*) "Europe/Brussels" , 0x03F103 }, + { (char*) "Europe/Bucharest" , 0x03F55E }, + { (char*) "Europe/Budapest" , 0x03F7FF }, + { (char*) "Europe/Busingen" , 0x03FB09 }, + { (char*) "Europe/Chisinau" , 0x03FD0E }, + { (char*) "Europe/Copenhagen" , 0x04000D }, + { (char*) "Europe/Dublin" , 0x040288 }, + { (char*) "Europe/Gibraltar" , 0x04086C }, + { (char*) "Europe/Guernsey" , 0x040D3C }, + { (char*) "Europe/Helsinki" , 0x041393 }, + { (char*) "Europe/Isle_of_Man" , 0x041580 }, + { (char*) "Europe/Istanbul" , 0x041BCB }, + { (char*) "Europe/Jersey" , 0x042087 }, + { (char*) "Europe/Kaliningrad" , 0x0426DE }, + { (char*) "Europe/Kiev" , 0x042A86 }, + { (char*) "Europe/Kirov" , 0x042CC0 }, + { (char*) "Europe/Kyiv" , 0x042FB9 }, + { (char*) "Europe/Lisbon" , 0x043202 }, + { (char*) "Europe/Ljubljana" , 0x0437D8 }, + { (char*) "Europe/London" , 0x0439C2 }, + { (char*) "Europe/Luxembourg" , 0x04400D }, + { (char*) "Europe/Madrid" , 0x044458 }, + { (char*) "Europe/Malta" , 0x0447F5 }, + { (char*) "Europe/Mariehamn" , 0x044BA1 }, + { (char*) "Europe/Minsk" , 0x044D8E }, + { (char*) "Europe/Monaco" , 0x0450C2 }, + { (char*) "Europe/Moscow" , 0x045528 }, + { (char*) "Europe/Nicosia" , 0x0458D4 }, + { (char*) "Europe/Oslo" , 0x045B35 }, + { (char*) "Europe/Paris" , 0x045DE5 }, + { (char*) "Europe/Podgorica" , 0x046242 }, + { (char*) "Europe/Prague" , 0x04642C }, + { (char*) "Europe/Riga" , 0x04670B }, + { (char*) "Europe/Rome" , 0x0469CD }, + { (char*) "Europe/Samara" , 0x046D8C }, + { (char*) "Europe/San_Marino" , 0x04708D }, + { (char*) "Europe/Sarajevo" , 0x04744C }, + { (char*) "Europe/Saratov" , 0x047636 }, + { (char*) "Europe/Simferopol" , 0x047928 }, + { (char*) "Europe/Skopje" , 0x047C9B }, + { (char*) "Europe/Sofia" , 0x047E85 }, + { (char*) "Europe/Stockholm" , 0x0480E1 }, + { (char*) "Europe/Tallinn" , 0x0482DE }, + { (char*) "Europe/Tirane" , 0x04858D }, + { (char*) "Europe/Tiraspol" , 0x0487F5 }, + { (char*) "Europe/Ulyanovsk" , 0x048AF4 }, + { (char*) "Europe/Uzhgorod" , 0x048E0A }, + { (char*) "Europe/Vaduz" , 0x049044 }, + { (char*) "Europe/Vatican" , 0x04922E }, + { (char*) "Europe/Vienna" , 0x0495ED }, + { (char*) "Europe/Vilnius" , 0x04988B }, + { (char*) "Europe/Volgograd" , 0x049B3B }, + { (char*) "Europe/Warsaw" , 0x049E4A }, + { (char*) "Europe/Zagreb" , 0x04A1F1 }, + { (char*) "Europe/Zaporozhye" , 0x04A3DB }, + { (char*) "Europe/Zurich" , 0x04A615 }, + { (char*) "Factory" , 0x04A812 }, + { (char*) "GB" , 0x04A88F }, + { (char*) "GB-Eire" , 0x04AEDA }, + { (char*) "GMT" , 0x04B525 }, + { (char*) "GMT+0" , 0x04B5A0 }, + { (char*) "GMT-0" , 0x04B61B }, + { (char*) "GMT0" , 0x04B696 }, + { (char*) "Greenwich" , 0x04B711 }, + { (char*) "Hongkong" , 0x04B78C }, + { (char*) "HST" , 0x04BA9F }, + { (char*) "Iceland" , 0x04BB88 }, + { (char*) "Indian/Antananarivo" , 0x04BC16 }, + { (char*) "Indian/Chagos" , 0x04BCC2 }, + { (char*) "Indian/Christmas" , 0x04BD66 }, + { (char*) "Indian/Cocos" , 0x04BDF7 }, + { (char*) "Indian/Comoro" , 0x04BE8F }, + { (char*) "Indian/Kerguelen" , 0x04BF1E }, + { (char*) "Indian/Mahe" , 0x04BFAF }, + { (char*) "Indian/Maldives" , 0x04C040 }, + { (char*) "Indian/Mauritius" , 0x04C0E4 }, + { (char*) "Indian/Mayotte" , 0x04C1A3 }, + { (char*) "Indian/Reunion" , 0x04C232 }, + { (char*) "Iran" , 0x04C2C3 }, + { (char*) "Israel" , 0x04C5FB }, + { (char*) "Jamaica" , 0x04CA39 }, + { (char*) "Japan" , 0x04CB98 }, + { (char*) "Kwajalein" , 0x04CC79 }, + { (char*) "Libya" , 0x04CD60 }, + { (char*) "MET" , 0x04CF1B }, + { (char*) "Mexico/BajaNorte" , 0x04D376 }, + { (char*) "Mexico/BajaSur" , 0x04D7B9 }, + { (char*) "Mexico/General" , 0x04DA77 }, + { (char*) "MST" , 0x04DD88 }, + { (char*) "MST7MDT" , 0x04DE84 }, + { (char*) "Navajo" , 0x04E2A2 }, + { (char*) "NZ" , 0x04E6C0 }, + { (char*) "NZ-CHAT" , 0x04EADF }, + { (char*) "Pacific/Apia" , 0x04EE13 }, + { (char*) "Pacific/Auckland" , 0x04EFB6 }, + { (char*) "Pacific/Bougainville" , 0x04F3E8 }, + { (char*) "Pacific/Chatham" , 0x04F4C9 }, + { (char*) "Pacific/Chuuk" , 0x04F80C }, + { (char*) "Pacific/Easter" , 0x04F8EA }, + { (char*) "Pacific/Efate" , 0x04FD99 }, + { (char*) "Pacific/Enderbury" , 0x04FEFB }, + { (char*) "Pacific/Fakaofo" , 0x04FFB3 }, + { (char*) "Pacific/Fiji" , 0x050058 }, + { (char*) "Pacific/Funafuti" , 0x0501F0 }, + { (char*) "Pacific/Galapagos" , 0x050282 }, + { (char*) "Pacific/Gambier" , 0x05034E }, + { (char*) "Pacific/Guadalcanal" , 0x0503ED }, + { (char*) "Pacific/Guam" , 0x05047F }, + { (char*) "Pacific/Honolulu" , 0x0505E9 }, + { (char*) "Pacific/Johnston" , 0x0506D8 }, + { (char*) "Pacific/Kanton" , 0x0507C1 }, + { (char*) "Pacific/Kiritimati" , 0x050888 }, + { (char*) "Pacific/Kosrae" , 0x05094E }, + { (char*) "Pacific/Kwajalein" , 0x050A52 }, + { (char*) "Pacific/Majuro" , 0x050B42 }, + { (char*) "Pacific/Marquesas" , 0x050C40 }, + { (char*) "Pacific/Midway" , 0x050CE8 }, + { (char*) "Pacific/Nauru" , 0x050DAB }, + { (char*) "Pacific/Niue" , 0x050E6E }, + { (char*) "Pacific/Norfolk" , 0x050F14 }, + { (char*) "Pacific/Noumea" , 0x05100D }, + { (char*) "Pacific/Pago_Pago" , 0x0510DF }, + { (char*) "Pacific/Palau" , 0x05117D }, + { (char*) "Pacific/Pitcairn" , 0x05121D }, + { (char*) "Pacific/Pohnpei" , 0x0512C2 }, + { (char*) "Pacific/Ponape" , 0x0513B2 }, + { (char*) "Pacific/Port_Moresby" , 0x051444 }, + { (char*) "Pacific/Rarotonga" , 0x051502 }, + { (char*) "Pacific/Saipan" , 0x0516A4 }, + { (char*) "Pacific/Samoa" , 0x051805 }, + { (char*) "Pacific/Tahiti" , 0x0518A3 }, + { (char*) "Pacific/Tarawa" , 0x051943 }, + { (char*) "Pacific/Tongatapu" , 0x0519E4 }, + { (char*) "Pacific/Truk" , 0x051ADD }, + { (char*) "Pacific/Wake" , 0x051B83 }, + { (char*) "Pacific/Wallis" , 0x051C20 }, + { (char*) "Pacific/Yap" , 0x051CB2 }, + { (char*) "Poland" , 0x051D58 }, + { (char*) "Portugal" , 0x0520FF }, + { (char*) "PRC" , 0x0526C2 }, + { (char*) "PST8PDT" , 0x052857 }, + { (char*) "ROC" , 0x052D71 }, + { (char*) "ROK" , 0x052F7C }, + { (char*) "Singapore" , 0x053127 }, + { (char*) "Turkey" , 0x053233 }, + { (char*) "UCT" , 0x0536EF }, + { (char*) "Universal" , 0x05376A }, + { (char*) "US/Alaska" , 0x0537E5 }, + { (char*) "US/Aleutian" , 0x053BC2 }, + { (char*) "US/Arizona" , 0x053F97 }, + { (char*) "US/Central" , 0x054093 }, + { (char*) "US/East-Indiana" , 0x054779 }, + { (char*) "US/Eastern" , 0x054998 }, + { (char*) "US/Hawaii" , 0x055074 }, + { (char*) "US/Indiana-Starke" , 0x05515D }, + { (char*) "US/Michigan" , 0x055561 }, + { (char*) "US/Mountain" , 0x0558F0 }, + { (char*) "US/Pacific" , 0x055D0E }, + { (char*) "US/Samoa" , 0x056228 }, + { (char*) "UTC" , 0x0562C6 }, + { (char*) "W-SU" , 0x056341 }, + { (char*) "WET" , 0x0566D9 }, + { (char*) "Zulu" , 0x056C9C }, }; -const unsigned char timelib_timezone_db_data_builtin[354224] = { +const unsigned char timelib_timezone_db_data_builtin[355607] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3709,6 +3710,95 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0xFF, +0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, +0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, +0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, +0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, +0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, +0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, +0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, +0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, +0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, 0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, +0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, +0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, +0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, 0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, +0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x87, 0x40, 0x00, +0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x60, 0x69, 0x40, 0x00, +0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, +0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, +0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, +0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x94, 0x40, 0x00, +0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, +0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, +0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, +0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, 0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, +0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, +0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, +0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, +0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, +0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x06, 0xFF, 0xFF, 0xBC, 0x70, +0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, +0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, +0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, +0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, +0x33, 0x0A, 0x00, 0x43, 0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, +0x73, 0x65, 0x6E, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -7899,9 +7989,8 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, -0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, -0x67, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, -0x65, 0x73, +0x33, 0x0A, 0x00, 0x38, 0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, +0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -13146,7 +13235,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -21311,7 +21400,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, +0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x29, 0xCB, 0x9C, 0xC8, 0x00, @@ -24240,7 +24329,7 @@ const unsigned char timelib_timezone_db_data_builtin[354224] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #else -const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { +const timelib_tzdb_index_entry timezonedb_idx_builtin[598] = { { (char*) "Africa/Abidjan" , 0x000000 }, { (char*) "Africa/Accra" , 0x0000A0 }, { (char*) "Africa/Addis_Ababa" , 0x0004D0 }, @@ -24340,508 +24429,509 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[597] = { { (char*) "America/Coral_Harbour" , 0x0114AF }, { (char*) "America/Cordoba" , 0x011571 }, { (char*) "America/Costa_Rica" , 0x0119A3 }, - { (char*) "America/Creston" , 0x011AEB }, - { (char*) "America/Cuiaba" , 0x011BD9 }, - { (char*) "America/Curacao" , 0x01216A }, - { (char*) "America/Danmarkshavn" , 0x012230 }, - { (char*) "America/Dawson" , 0x012510 }, - { (char*) "America/Dawson_Creek" , 0x012B7C }, - { (char*) "America/Denver" , 0x012FC2 }, - { (char*) "America/Detroit" , 0x01397F }, - { (char*) "America/Dominica" , 0x01425A }, - { (char*) "America/Edmonton" , 0x0142FA }, - { (char*) "America/Eirunepe" , 0x014C44 }, - { (char*) "America/El_Salvador" , 0x014EE1 }, - { (char*) "America/Ensenada" , 0x014FCD }, - { (char*) "America/Fort_Nelson" , 0x015973 }, - { (char*) "America/Fort_Wayne" , 0x016253 }, - { (char*) "America/Fortaleza" , 0x0168F1 }, - { (char*) "America/Glace_Bay" , 0x016BE1 }, - { (char*) "America/Godthab" , 0x017498 }, - { (char*) "America/Goose_Bay" , 0x017C05 }, - { (char*) "America/Grand_Turk" , 0x0188BB }, - { (char*) "America/Grenada" , 0x018FF1 }, - { (char*) "America/Guadeloupe" , 0x019091 }, - { (char*) "America/Guatemala" , 0x019131 }, - { (char*) "America/Guayaquil" , 0x019255 }, - { (char*) "America/Guyana" , 0x01935B }, - { (char*) "America/Halifax" , 0x01945F }, - { (char*) "America/Havana" , 0x01A1E9 }, - { (char*) "America/Hermosillo" , 0x01AB65 }, - { (char*) "America/Indiana/Indianapolis" , 0x01ACFB }, - { (char*) "America/Indiana/Knox" , 0x01B3B2 }, - { (char*) "America/Indiana/Marengo" , 0x01BD5F }, - { (char*) "America/Indiana/Petersburg" , 0x01C44C }, - { (char*) "America/Indiana/Tell_City" , 0x01CBEB }, - { (char*) "America/Indiana/Vevay" , 0x01D2AF }, - { (char*) "America/Indiana/Vincennes" , 0x01D86B }, - { (char*) "America/Indiana/Winamac" , 0x01DF41 }, - { (char*) "America/Indianapolis" , 0x01E665 }, - { (char*) "America/Inuvik" , 0x01ED03 }, - { (char*) "America/Iqaluit" , 0x01F53D }, - { (char*) "America/Jamaica" , 0x01FDFC }, - { (char*) "America/Jujuy" , 0x01FFEA }, - { (char*) "America/Juneau" , 0x020400 }, - { (char*) "America/Kentucky/Louisville" , 0x020D51 }, - { (char*) "America/Kentucky/Monticello" , 0x02185F }, - { (char*) "America/Knox_IN" , 0x0221BF }, - { (char*) "America/Kralendijk" , 0x022B57 }, - { (char*) "America/La_Paz" , 0x022C59 }, - { (char*) "America/Lima" , 0x022D3F }, - { (char*) "America/Los_Angeles" , 0x022ED3 }, - { (char*) "America/Louisville" , 0x023A0A }, - { (char*) "America/Lower_Princes" , 0x0244FA }, - { (char*) "America/Maceio" , 0x0245FC }, - { (char*) "America/Managua" , 0x0248F2 }, - { (char*) "America/Manaus" , 0x024AAC }, - { (char*) "America/Marigot" , 0x024D15 }, - { (char*) "America/Martinique" , 0x024E17 }, - { (char*) "America/Matamoros" , 0x024F0B }, - { (char*) "America/Mazatlan" , 0x0254CD }, - { (char*) "America/Mendoza" , 0x02592F }, - { (char*) "America/Menominee" , 0x025D61 }, - { (char*) "America/Merida" , 0x02666E }, - { (char*) "America/Metlakatla" , 0x026A77 }, - { (char*) "America/Mexico_City" , 0x027029 }, - { (char*) "America/Miquelon" , 0x027509 }, - { (char*) "America/Moncton" , 0x027B89 }, - { (char*) "America/Monterrey" , 0x0287FF }, - { (char*) "America/Montevideo" , 0x028C9B }, - { (char*) "America/Montreal" , 0x02927F }, - { (char*) "America/Montserrat" , 0x02A031 }, - { (char*) "America/Nassau" , 0x02A0D1 }, - { (char*) "America/New_York" , 0x02AA31 }, - { (char*) "America/Nipigon" , 0x02B831 }, - { (char*) "America/Nome" , 0x02C5E3 }, - { (char*) "America/Noronha" , 0x02CF3B }, - { (char*) "America/North_Dakota/Beulah" , 0x02D215 }, - { (char*) "America/North_Dakota/Center" , 0x02DB92 }, - { (char*) "America/North_Dakota/New_Salem" , 0x02E50F }, - { (char*) "America/Nuuk" , 0x02EE92 }, - { (char*) "America/Ojinaga" , 0x02F610 }, - { (char*) "America/Panama" , 0x02FC2C }, - { (char*) "America/Pangnirtung" , 0x02FCEE }, - { (char*) "America/Paramaribo" , 0x030594 }, - { (char*) "America/Phoenix" , 0x030698 }, - { (char*) "America/Port-au-Prince" , 0x030824 }, - { (char*) "America/Port_of_Spain" , 0x030DCA }, - { (char*) "America/Porto_Acre" , 0x030E6A }, - { (char*) "America/Porto_Velho" , 0x0310DC }, - { (char*) "America/Puerto_Rico" , 0x031322 }, - { (char*) "America/Punta_Arenas" , 0x031424 }, - { (char*) "America/Rainy_River" , 0x031BB2 }, - { (char*) "America/Rankin_Inlet" , 0x0326F2 }, - { (char*) "America/Recife" , 0x032F26 }, - { (char*) "America/Regina" , 0x0331FA }, - { (char*) "America/Resolute" , 0x0335EF }, - { (char*) "America/Rio_Branco" , 0x033E24 }, - { (char*) "America/Rosario" , 0x03409A }, - { (char*) "America/Santa_Isabel" , 0x0344CC }, - { (char*) "America/Santarem" , 0x034E72 }, - { (char*) "America/Santiago" , 0x0350D5 }, - { (char*) "America/Santo_Domingo" , 0x035AC1 }, - { (char*) "America/Sao_Paulo" , 0x035C97 }, - { (char*) "America/Scoresbysund" , 0x03626F }, - { (char*) "America/Shiprock" , 0x036A27 }, - { (char*) "America/Sitka" , 0x0373CF }, - { (char*) "America/St_Barthelemy" , 0x037D07 }, - { (char*) "America/St_Johns" , 0x037E09 }, - { (char*) "America/St_Kitts" , 0x038C77 }, - { (char*) "America/St_Lucia" , 0x038D17 }, - { (char*) "America/St_Thomas" , 0x038DD9 }, - { (char*) "America/St_Vincent" , 0x038E79 }, - { (char*) "America/Swift_Current" , 0x038F3B }, - { (char*) "America/Tegucigalpa" , 0x039189 }, - { (char*) "America/Thule" , 0x039291 }, - { (char*) "America/Thunder_Bay" , 0x039889 }, - { (char*) "America/Tijuana" , 0x03A63B }, - { (char*) "America/Toronto" , 0x03AFF0 }, - { (char*) "America/Tortola" , 0x03BDC0 }, - { (char*) "America/Vancouver" , 0x03BE60 }, - { (char*) "America/Virgin" , 0x03C9D1 }, - { (char*) "America/Whitehorse" , 0x03CAD3 }, - { (char*) "America/Winnipeg" , 0x03D13F }, - { (char*) "America/Yakutat" , 0x03DC9C }, - { (char*) "America/Yellowknife" , 0x03E5B9 }, - { (char*) "Antarctica/Casey" , 0x03EEE1 }, - { (char*) "Antarctica/Davis" , 0x03F099 }, - { (char*) "Antarctica/DumontDUrville" , 0x03F1C5 }, - { (char*) "Antarctica/Macquarie" , 0x03F295 }, - { (char*) "Antarctica/Mawson" , 0x03FB85 }, - { (char*) "Antarctica/McMurdo" , 0x03FC50 }, - { (char*) "Antarctica/Palmer" , 0x04044B }, - { (char*) "Antarctica/Rothera" , 0x0409D9 }, - { (char*) "Antarctica/South_Pole" , 0x040A82 }, - { (char*) "Antarctica/Syowa" , 0x041413 }, - { (char*) "Antarctica/Troll" , 0x0414BB }, - { (char*) "Antarctica/Vostok" , 0x041948 }, - { (char*) "Arctic/Longyearbyen" , 0x041A2F }, - { (char*) "Asia/Aden" , 0x042335 }, - { (char*) "Asia/Almaty" , 0x0423D8 }, - { (char*) "Asia/Amman" , 0x0427CD }, - { (char*) "Asia/Anadyr" , 0x042D72 }, - { (char*) "Asia/Aqtau" , 0x043227 }, - { (char*) "Asia/Aqtobe" , 0x043611 }, - { (char*) "Asia/Ashgabat" , 0x043A0F }, - { (char*) "Asia/Ashkhabad" , 0x043C78 }, - { (char*) "Asia/Atyrau" , 0x043EE1 }, - { (char*) "Asia/Baghdad" , 0x0442D3 }, - { (char*) "Asia/Bahrain" , 0x0446A8 }, - { (char*) "Asia/Baku" , 0x044793 }, - { (char*) "Asia/Bangkok" , 0x044C5C }, - { (char*) "Asia/Barnaul" , 0x044D21 }, - { (char*) "Asia/Beirut" , 0x0451F2 }, - { (char*) "Asia/Bishkek" , 0x045A68 }, - { (char*) "Asia/Brunei" , 0x045E3D }, - { (char*) "Asia/Calcutta" , 0x045F06 }, - { (char*) "Asia/Chita" , 0x04602F }, - { (char*) "Asia/Choibalsan" , 0x046506 }, - { (char*) "Asia/Chongqing" , 0x04687F }, - { (char*) "Asia/Chungking" , 0x046ABC }, - { (char*) "Asia/Colombo" , 0x046CF9 }, - { (char*) "Asia/Dacca" , 0x046E6B }, - { (char*) "Asia/Damascus" , 0x046FBA }, - { (char*) "Asia/Dhaka" , 0x047717 }, - { (char*) "Asia/Dili" , 0x047866 }, - { (char*) "Asia/Dubai" , 0x047973 }, - { (char*) "Asia/Dushanbe" , 0x047A16 }, - { (char*) "Asia/Famagusta" , 0x047C63 }, - { (char*) "Asia/Gaza" , 0x04846A }, - { (char*) "Asia/Harbin" , 0x049384 }, - { (char*) "Asia/Hebron" , 0x0495C1 }, - { (char*) "Asia/Ho_Chi_Minh" , 0x04A4F6 }, - { (char*) "Asia/Hong_Kong" , 0x04A653 }, - { (char*) "Asia/Hovd" , 0x04AB30 }, - { (char*) "Asia/Irkutsk" , 0x04AEBF }, - { (char*) "Asia/Istanbul" , 0x04B3B2 }, - { (char*) "Asia/Jakarta" , 0x04BB4B }, - { (char*) "Asia/Jayapura" , 0x04BCE3 }, - { (char*) "Asia/Jerusalem" , 0x04BE02 }, - { (char*) "Asia/Kabul" , 0x04C762 }, - { (char*) "Asia/Kamchatka" , 0x04C830 }, - { (char*) "Asia/Karachi" , 0x04CCCE }, - { (char*) "Asia/Kashgar" , 0x04CE55 }, - { (char*) "Asia/Kathmandu" , 0x04CEF8 }, - { (char*) "Asia/Katmandu" , 0x04CFCA }, - { (char*) "Asia/Khandyga" , 0x04D09C }, - { (char*) "Asia/Kolkata" , 0x04D5AF }, - { (char*) "Asia/Krasnoyarsk" , 0x04D6D8 }, - { (char*) "Asia/Kuala_Lumpur" , 0x04DBA6 }, - { (char*) "Asia/Kuching" , 0x04DD57 }, - { (char*) "Asia/Kuwait" , 0x04DF46 }, - { (char*) "Asia/Macao" , 0x04DFE9 }, - { (char*) "Asia/Macau" , 0x04E4C0 }, - { (char*) "Asia/Magadan" , 0x04E997 }, - { (char*) "Asia/Makassar" , 0x04EE6B }, - { (char*) "Asia/Manila" , 0x04EFBE }, - { (char*) "Asia/Muscat" , 0x04F170 }, - { (char*) "Asia/Nicosia" , 0x04F213 }, - { (char*) "Asia/Novokuznetsk" , 0x04F9FF }, - { (char*) "Asia/Novosibirsk" , 0x04FE9B }, - { (char*) "Asia/Omsk" , 0x050372 }, - { (char*) "Asia/Oral" , 0x050834 }, - { (char*) "Asia/Phnom_Penh" , 0x050C2E }, - { (char*) "Asia/Pontianak" , 0x050D53 }, - { (char*) "Asia/Pyongyang" , 0x050ED6 }, - { (char*) "Asia/Qatar" , 0x050FCF }, - { (char*) "Asia/Qostanay" , 0x051094 }, - { (char*) "Asia/Qyzylorda" , 0x0514BB }, - { (char*) "Asia/Rangoon" , 0x0518D7 }, - { (char*) "Asia/Riyadh" , 0x0519E1 }, - { (char*) "Asia/Saigon" , 0x051A84 }, - { (char*) "Asia/Sakhalin" , 0x051BE1 }, - { (char*) "Asia/Samarkand" , 0x0520A9 }, - { (char*) "Asia/Seoul" , 0x0522F9 }, - { (char*) "Asia/Shanghai" , 0x05256E }, - { (char*) "Asia/Singapore" , 0x0527B7 }, - { (char*) "Asia/Srednekolymsk" , 0x052954 }, - { (char*) "Asia/Taipei" , 0x052E28 }, - { (char*) "Asia/Tashkent" , 0x05312D }, - { (char*) "Asia/Tbilisi" , 0x05338B }, - { (char*) "Asia/Tehran" , 0x053794 }, - { (char*) "Asia/Tel_Aviv" , 0x053C80 }, - { (char*) "Asia/Thimbu" , 0x0545E0 }, - { (char*) "Asia/Thimphu" , 0x0546A9 }, - { (char*) "Asia/Tokyo" , 0x054772 }, - { (char*) "Asia/Tomsk" , 0x0548B3 }, - { (char*) "Asia/Ujung_Pandang" , 0x054D84 }, - { (char*) "Asia/Ulaanbaatar" , 0x054E8E }, - { (char*) "Asia/Ulan_Bator" , 0x055217 }, - { (char*) "Asia/Urumqi" , 0x055590 }, - { (char*) "Asia/Ust-Nera" , 0x055640 }, - { (char*) "Asia/Vientiane" , 0x055B36 }, - { (char*) "Asia/Vladivostok" , 0x055C77 }, - { (char*) "Asia/Yakutsk" , 0x056140 }, - { (char*) "Asia/Yangon" , 0x056608 }, - { (char*) "Asia/Yekaterinburg" , 0x056712 }, - { (char*) "Asia/Yerevan" , 0x056BF9 }, - { (char*) "Atlantic/Azores" , 0x057076 }, - { (char*) "Atlantic/Bermuda" , 0x057DFA }, - { (char*) "Atlantic/Canary" , 0x058762 }, - { (char*) "Atlantic/Cape_Verde" , 0x058EE5 }, - { (char*) "Atlantic/Faeroe" , 0x058FF1 }, - { (char*) "Atlantic/Faroe" , 0x059714 }, - { (char*) "Atlantic/Jan_Mayen" , 0x059E37 }, - { (char*) "Atlantic/Madeira" , 0x05A73D }, - { (char*) "Atlantic/Reykjavik" , 0x05B489 }, - { (char*) "Atlantic/South_Georgia" , 0x05B91F }, - { (char*) "Atlantic/St_Helena" , 0x05B9C1 }, - { (char*) "Atlantic/Stanley" , 0x05BA83 }, - { (char*) "Australia/ACT" , 0x05BF3F }, - { (char*) "Australia/Adelaide" , 0x05C7D9 }, - { (char*) "Australia/Brisbane" , 0x05D094 }, - { (char*) "Australia/Broken_Hill" , 0x05D25A }, - { (char*) "Australia/Canberra" , 0x05DB37 }, - { (char*) "Australia/Currie" , 0x05E3D1 }, - { (char*) "Australia/Darwin" , 0x05ED13 }, - { (char*) "Australia/Eucla" , 0x05EE76 }, - { (char*) "Australia/Hobart" , 0x05F063 }, - { (char*) "Australia/LHI" , 0x05F9AD }, - { (char*) "Australia/Lindeman" , 0x0600EF }, - { (char*) "Australia/Lord_Howe" , 0x0602F5 }, - { (char*) "Australia/Melbourne" , 0x060A47 }, - { (char*) "Australia/North" , 0x0612E9 }, - { (char*) "Australia/NSW" , 0x06143A }, - { (char*) "Australia/Perth" , 0x061CD4 }, - { (char*) "Australia/Queensland" , 0x061EBC }, - { (char*) "Australia/South" , 0x06206B }, - { (char*) "Australia/Sydney" , 0x062917 }, - { (char*) "Australia/Tasmania" , 0x0631CD }, - { (char*) "Australia/Victoria" , 0x063B0F }, - { (char*) "Australia/West" , 0x0643A9 }, - { (char*) "Australia/Yancowinna" , 0x064573 }, - { (char*) "Brazil/Acre" , 0x064E34 }, - { (char*) "Brazil/DeNoronha" , 0x0650A6 }, - { (char*) "Brazil/East" , 0x065370 }, - { (char*) "Brazil/West" , 0x065912 }, - { (char*) "Canada/Atlantic" , 0x065B6C }, - { (char*) "Canada/Central" , 0x0668D8 }, - { (char*) "Canada/Eastern" , 0x067418 }, - { (char*) "Canada/Mountain" , 0x0681CA }, - { (char*) "Canada/Newfoundland" , 0x068AF2 }, - { (char*) "Canada/Pacific" , 0x069945 }, - { (char*) "Canada/Saskatchewan" , 0x06A49D }, - { (char*) "Canada/Yukon" , 0x06A87D }, - { (char*) "CET" , 0x06AED7 }, - { (char*) "Chile/Continental" , 0x06BA58 }, - { (char*) "Chile/EasterIsland" , 0x06C437 }, - { (char*) "CST6CDT" , 0x06CCEE }, - { (char*) "Cuba" , 0x06DB02 }, - { (char*) "EET" , 0x06E47E }, - { (char*) "Egypt" , 0x06ED60 }, - { (char*) "Eire" , 0x06F6CB }, - { (char*) "EST" , 0x07047B }, - { (char*) "EST5EDT" , 0x07053D }, - { (char*) "Etc/GMT" , 0x071329 }, - { (char*) "Etc/GMT+0" , 0x0713A7 }, - { (char*) "Etc/GMT+1" , 0x071425 }, - { (char*) "Etc/GMT+10" , 0x0714A5 }, - { (char*) "Etc/GMT+11" , 0x071526 }, - { (char*) "Etc/GMT+12" , 0x0715A7 }, - { (char*) "Etc/GMT+2" , 0x071628 }, - { (char*) "Etc/GMT+3" , 0x0716A8 }, - { (char*) "Etc/GMT+4" , 0x071728 }, - { (char*) "Etc/GMT+5" , 0x0717A8 }, - { (char*) "Etc/GMT+6" , 0x071828 }, - { (char*) "Etc/GMT+7" , 0x0718A8 }, - { (char*) "Etc/GMT+8" , 0x071928 }, - { (char*) "Etc/GMT+9" , 0x0719A8 }, - { (char*) "Etc/GMT-0" , 0x071A28 }, - { (char*) "Etc/GMT-1" , 0x071AA6 }, - { (char*) "Etc/GMT-10" , 0x071B27 }, - { (char*) "Etc/GMT-11" , 0x071BA9 }, - { (char*) "Etc/GMT-12" , 0x071C2B }, - { (char*) "Etc/GMT-13" , 0x071CAD }, - { (char*) "Etc/GMT-14" , 0x071D2F }, - { (char*) "Etc/GMT-2" , 0x071DB1 }, - { (char*) "Etc/GMT-3" , 0x071E32 }, - { (char*) "Etc/GMT-4" , 0x071EB3 }, - { (char*) "Etc/GMT-5" , 0x071F34 }, - { (char*) "Etc/GMT-6" , 0x071FB5 }, - { (char*) "Etc/GMT-7" , 0x072036 }, - { (char*) "Etc/GMT-8" , 0x0720B7 }, - { (char*) "Etc/GMT-9" , 0x072138 }, - { (char*) "Etc/GMT0" , 0x0721B9 }, - { (char*) "Etc/Greenwich" , 0x072237 }, - { (char*) "Etc/UCT" , 0x0722B5 }, - { (char*) "Etc/Universal" , 0x072333 }, - { (char*) "Etc/UTC" , 0x0723B1 }, - { (char*) "Etc/Zulu" , 0x07242F }, - { (char*) "Europe/Amsterdam" , 0x0724AD }, - { (char*) "Europe/Andorra" , 0x073017 }, - { (char*) "Europe/Astrakhan" , 0x0736F1 }, - { (char*) "Europe/Athens" , 0x073B8E }, - { (char*) "Europe/Belfast" , 0x074470 }, - { (char*) "Europe/Belgrade" , 0x0752CC }, - { (char*) "Europe/Berlin" , 0x075A58 }, - { (char*) "Europe/Bratislava" , 0x07636D }, - { (char*) "Europe/Brussels" , 0x076C76 }, - { (char*) "Europe/Bucharest" , 0x0777F7 }, - { (char*) "Europe/Budapest" , 0x07808B }, - { (char*) "Europe/Busingen" , 0x0789D7 }, - { (char*) "Europe/Chisinau" , 0x079160 }, - { (char*) "Europe/Copenhagen" , 0x079AC2 }, - { (char*) "Europe/Dublin" , 0x07A327 }, - { (char*) "Europe/Gibraltar" , 0x07B0D7 }, - { (char*) "Europe/Guernsey" , 0x07BCDF }, - { (char*) "Europe/Helsinki" , 0x07CB7F }, - { (char*) "Europe/Isle_of_Man" , 0x07D2F7 }, - { (char*) "Europe/Istanbul" , 0x07E143 }, - { (char*) "Europe/Jersey" , 0x07E8DC }, - { (char*) "Europe/Kaliningrad" , 0x07F77C }, - { (char*) "Europe/Kiev" , 0x07FD71 }, - { (char*) "Europe/Kirov" , 0x0805C5 }, - { (char*) "Europe/Kyiv" , 0x080A80 }, - { (char*) "Europe/Lisbon" , 0x0812E3 }, - { (char*) "Europe/Ljubljana" , 0x0820C9 }, - { (char*) "Europe/London" , 0x082855 }, - { (char*) "Europe/Luxembourg" , 0x0836B1 }, - { (char*) "Europe/Madrid" , 0x08423F }, - { (char*) "Europe/Malta" , 0x084C91 }, - { (char*) "Europe/Mariehamn" , 0x0856D9 }, - { (char*) "Europe/Minsk" , 0x085E51 }, - { (char*) "Europe/Monaco" , 0x086378 }, - { (char*) "Europe/Moscow" , 0x086F04 }, - { (char*) "Europe/Nicosia" , 0x087523 }, - { (char*) "Europe/Oslo" , 0x087D01 }, - { (char*) "Europe/Paris" , 0x0885C1 }, - { (char*) "Europe/Podgorica" , 0x08915F }, - { (char*) "Europe/Prague" , 0x0898EB }, - { (char*) "Europe/Riga" , 0x08A1F4 }, - { (char*) "Europe/Rome" , 0x08AA96 }, - { (char*) "Europe/Samara" , 0x08B4F3 }, - { (char*) "Europe/San_Marino" , 0x08B9C9 }, - { (char*) "Europe/Sarajevo" , 0x08C426 }, - { (char*) "Europe/Saratov" , 0x08CBB2 }, - { (char*) "Europe/Simferopol" , 0x08D05F }, - { (char*) "Europe/Skopje" , 0x08D62E }, - { (char*) "Europe/Sofia" , 0x08DDBA }, - { (char*) "Europe/Stockholm" , 0x08E5E3 }, - { (char*) "Europe/Tallinn" , 0x08ED64 }, - { (char*) "Europe/Tirane" , 0x08F5D4 }, - { (char*) "Europe/Tiraspol" , 0x08FE04 }, - { (char*) "Europe/Ulyanovsk" , 0x090766 }, - { (char*) "Europe/Uzhgorod" , 0x090C69 }, - { (char*) "Europe/Vaduz" , 0x0914BD }, - { (char*) "Europe/Vatican" , 0x091C29 }, - { (char*) "Europe/Vienna" , 0x092686 }, - { (char*) "Europe/Vilnius" , 0x092F2A }, - { (char*) "Europe/Volgograd" , 0x0937A8 }, - { (char*) "Europe/Warsaw" , 0x093C6F }, - { (char*) "Europe/Zagreb" , 0x0946D9 }, - { (char*) "Europe/Zaporozhye" , 0x094E65 }, - { (char*) "Europe/Zurich" , 0x0956B9 }, - { (char*) "Factory" , 0x095E3A }, - { (char*) "GB" , 0x095EBA }, - { (char*) "GB-Eire" , 0x096D16 }, - { (char*) "GMT" , 0x097B72 }, - { (char*) "GMT+0" , 0x097BF0 }, - { (char*) "GMT-0" , 0x097C6E }, - { (char*) "GMT0" , 0x097CEC }, - { (char*) "Greenwich" , 0x097D6A }, - { (char*) "Hongkong" , 0x097DE8 }, - { (char*) "HST" , 0x0982C5 }, - { (char*) "Iceland" , 0x09841A }, - { (char*) "Indian/Antananarivo" , 0x0984BA }, - { (char*) "Indian/Chagos" , 0x0985A1 }, - { (char*) "Indian/Christmas" , 0x098666 }, - { (char*) "Indian/Cocos" , 0x098709 }, - { (char*) "Indian/Comoro" , 0x0987B5 }, - { (char*) "Indian/Kerguelen" , 0x098856 }, - { (char*) "Indian/Mahe" , 0x0988F9 }, - { (char*) "Indian/Maldives" , 0x09899C }, - { (char*) "Indian/Mauritius" , 0x098A61 }, - { (char*) "Indian/Mayotte" , 0x098B50 }, - { (char*) "Indian/Reunion" , 0x098BF1 }, - { (char*) "Iran" , 0x098C94 }, - { (char*) "Israel" , 0x099180 }, - { (char*) "Jamaica" , 0x099AE0 }, - { (char*) "Japan" , 0x099CCE }, - { (char*) "Kwajalein" , 0x099E0F }, - { (char*) "Libya" , 0x099F49 }, - { (char*) "MET" , 0x09A1C6 }, - { (char*) "Mexico/BajaNorte" , 0x09AD47 }, - { (char*) "Mexico/BajaSur" , 0x09B6ED }, - { (char*) "Mexico/General" , 0x09BB1D }, - { (char*) "MST" , 0x09BFEF }, - { (char*) "MST7MDT" , 0x09C163 }, - { (char*) "Navajo" , 0x09CB0B }, - { (char*) "NZ" , 0x09D4B3 }, - { (char*) "NZ-CHAT" , 0x09DE44 }, - { (char*) "Pacific/Apia" , 0x09E656 }, - { (char*) "Pacific/Auckland" , 0x09E8B8 }, - { (char*) "Pacific/Bougainville" , 0x09F25C }, - { (char*) "Pacific/Chatham" , 0x09F372 }, - { (char*) "Pacific/Chuuk" , 0x09FB93 }, - { (char*) "Pacific/Easter" , 0x09FCAD }, - { (char*) "Pacific/Efate" , 0x0A0571 }, - { (char*) "Pacific/Enderbury" , 0x0A0789 }, - { (char*) "Pacific/Fakaofo" , 0x0A0871 }, - { (char*) "Pacific/Fiji" , 0x0A0937 }, - { (char*) "Pacific/Funafuti" , 0x0A0B77 }, - { (char*) "Pacific/Galapagos" , 0x0A0C1B }, - { (char*) "Pacific/Gambier" , 0x0A0D18 }, - { (char*) "Pacific/Guadalcanal" , 0x0A0DC9 }, - { (char*) "Pacific/Guam" , 0x0A0E6D }, - { (char*) "Pacific/Honolulu" , 0x0A1067 }, - { (char*) "Pacific/Johnston" , 0x0A11C2 }, - { (char*) "Pacific/Kanton" , 0x0A1317 }, - { (char*) "Pacific/Kiritimati" , 0x0A140E }, - { (char*) "Pacific/Kosrae" , 0x0A1506 }, - { (char*) "Pacific/Kwajalein" , 0x0A1669 }, - { (char*) "Pacific/Majuro" , 0x0A17AC }, - { (char*) "Pacific/Marquesas" , 0x0A18F8 }, - { (char*) "Pacific/Midway" , 0x0A19B4 }, - { (char*) "Pacific/Nauru" , 0x0A1AA7 }, - { (char*) "Pacific/Niue" , 0x0A1BA1 }, - { (char*) "Pacific/Norfolk" , 0x0A1C6A }, - { (char*) "Pacific/Noumea" , 0x0A1FD8 }, - { (char*) "Pacific/Pago_Pago" , 0x0A2106 }, - { (char*) "Pacific/Palau" , 0x0A21C1 }, - { (char*) "Pacific/Pitcairn" , 0x0A2273 }, - { (char*) "Pacific/Pohnpei" , 0x0A233B }, - { (char*) "Pacific/Ponape" , 0x0A2476 }, - { (char*) "Pacific/Port_Moresby" , 0x0A251A }, - { (char*) "Pacific/Rarotonga" , 0x0A25EA }, - { (char*) "Pacific/Saipan" , 0x0A2843 }, - { (char*) "Pacific/Samoa" , 0x0A2A2F }, - { (char*) "Pacific/Tahiti" , 0x0A2AEA }, - { (char*) "Pacific/Tarawa" , 0x0A2B9C }, - { (char*) "Pacific/Tongatapu" , 0x0A2C4F }, - { (char*) "Pacific/Truk" , 0x0A2DC1 }, - { (char*) "Pacific/Wake" , 0x0A2E79 }, - { (char*) "Pacific/Wallis" , 0x0A2F28 }, - { (char*) "Pacific/Yap" , 0x0A2FCC }, - { (char*) "Poland" , 0x0A3084 }, - { (char*) "Portugal" , 0x0A3AEE }, - { (char*) "PRC" , 0x0A48C1 }, - { (char*) "PST8PDT" , 0x0A4AFE }, - { (char*) "ROC" , 0x0A562E }, - { (char*) "ROK" , 0x0A5933 }, - { (char*) "Singapore" , 0x0A5BA8 }, - { (char*) "Turkey" , 0x0A5D45 }, - { (char*) "UCT" , 0x0A64DE }, - { (char*) "Universal" , 0x0A655C }, - { (char*) "US/Alaska" , 0x0A65DA }, - { (char*) "US/Aleutian" , 0x0A6F29 }, - { (char*) "US/Arizona" , 0x0A7869 }, - { (char*) "US/Central" , 0x0A79DD }, - { (char*) "US/East-Indiana" , 0x0A87F1 }, - { (char*) "US/Eastern" , 0x0A8E8F }, - { (char*) "US/Hawaii" , 0x0A9C7B }, - { (char*) "US/Indiana-Starke" , 0x0A9DD0 }, - { (char*) "US/Michigan" , 0x0AA768 }, - { (char*) "US/Mountain" , 0x0AB02A }, - { (char*) "US/Pacific" , 0x0AB9D2 }, - { (char*) "US/Samoa" , 0x0AC502 }, - { (char*) "UTC" , 0x0AC5BD }, - { (char*) "W-SU" , 0x0AC63B }, - { (char*) "WET" , 0x0ACC46 }, - { (char*) "Zulu" , 0x0ADA19 }, + { (char*) "America/Coyhaique" , 0x011AEB }, + { (char*) "America/Creston" , 0x012351 }, + { (char*) "America/Cuiaba" , 0x01243F }, + { (char*) "America/Curacao" , 0x0129D0 }, + { (char*) "America/Danmarkshavn" , 0x012A96 }, + { (char*) "America/Dawson" , 0x012D76 }, + { (char*) "America/Dawson_Creek" , 0x0133E2 }, + { (char*) "America/Denver" , 0x013828 }, + { (char*) "America/Detroit" , 0x0141E5 }, + { (char*) "America/Dominica" , 0x014AC0 }, + { (char*) "America/Edmonton" , 0x014B60 }, + { (char*) "America/Eirunepe" , 0x0154AA }, + { (char*) "America/El_Salvador" , 0x015747 }, + { (char*) "America/Ensenada" , 0x015833 }, + { (char*) "America/Fort_Nelson" , 0x0161D9 }, + { (char*) "America/Fort_Wayne" , 0x016AB9 }, + { (char*) "America/Fortaleza" , 0x017157 }, + { (char*) "America/Glace_Bay" , 0x017447 }, + { (char*) "America/Godthab" , 0x017CFE }, + { (char*) "America/Goose_Bay" , 0x01846B }, + { (char*) "America/Grand_Turk" , 0x019121 }, + { (char*) "America/Grenada" , 0x019857 }, + { (char*) "America/Guadeloupe" , 0x0198F7 }, + { (char*) "America/Guatemala" , 0x019997 }, + { (char*) "America/Guayaquil" , 0x019ABB }, + { (char*) "America/Guyana" , 0x019BC1 }, + { (char*) "America/Halifax" , 0x019CC5 }, + { (char*) "America/Havana" , 0x01AA4F }, + { (char*) "America/Hermosillo" , 0x01B3CB }, + { (char*) "America/Indiana/Indianapolis" , 0x01B561 }, + { (char*) "America/Indiana/Knox" , 0x01BC18 }, + { (char*) "America/Indiana/Marengo" , 0x01C5C5 }, + { (char*) "America/Indiana/Petersburg" , 0x01CCB2 }, + { (char*) "America/Indiana/Tell_City" , 0x01D451 }, + { (char*) "America/Indiana/Vevay" , 0x01DB15 }, + { (char*) "America/Indiana/Vincennes" , 0x01E0D1 }, + { (char*) "America/Indiana/Winamac" , 0x01E7A7 }, + { (char*) "America/Indianapolis" , 0x01EECB }, + { (char*) "America/Inuvik" , 0x01F569 }, + { (char*) "America/Iqaluit" , 0x01FDA3 }, + { (char*) "America/Jamaica" , 0x020662 }, + { (char*) "America/Jujuy" , 0x020850 }, + { (char*) "America/Juneau" , 0x020C66 }, + { (char*) "America/Kentucky/Louisville" , 0x0215B7 }, + { (char*) "America/Kentucky/Monticello" , 0x0220C5 }, + { (char*) "America/Knox_IN" , 0x022A25 }, + { (char*) "America/Kralendijk" , 0x0233BD }, + { (char*) "America/La_Paz" , 0x0234BF }, + { (char*) "America/Lima" , 0x0235A5 }, + { (char*) "America/Los_Angeles" , 0x023739 }, + { (char*) "America/Louisville" , 0x024270 }, + { (char*) "America/Lower_Princes" , 0x024D60 }, + { (char*) "America/Maceio" , 0x024E62 }, + { (char*) "America/Managua" , 0x025158 }, + { (char*) "America/Manaus" , 0x025312 }, + { (char*) "America/Marigot" , 0x02557B }, + { (char*) "America/Martinique" , 0x02567D }, + { (char*) "America/Matamoros" , 0x025771 }, + { (char*) "America/Mazatlan" , 0x025D33 }, + { (char*) "America/Mendoza" , 0x026195 }, + { (char*) "America/Menominee" , 0x0265C7 }, + { (char*) "America/Merida" , 0x026ED4 }, + { (char*) "America/Metlakatla" , 0x0272DD }, + { (char*) "America/Mexico_City" , 0x02788F }, + { (char*) "America/Miquelon" , 0x027D6F }, + { (char*) "America/Moncton" , 0x0283EF }, + { (char*) "America/Monterrey" , 0x029065 }, + { (char*) "America/Montevideo" , 0x029501 }, + { (char*) "America/Montreal" , 0x029AE5 }, + { (char*) "America/Montserrat" , 0x02A897 }, + { (char*) "America/Nassau" , 0x02A937 }, + { (char*) "America/New_York" , 0x02B297 }, + { (char*) "America/Nipigon" , 0x02C097 }, + { (char*) "America/Nome" , 0x02CE49 }, + { (char*) "America/Noronha" , 0x02D7A1 }, + { (char*) "America/North_Dakota/Beulah" , 0x02DA7B }, + { (char*) "America/North_Dakota/Center" , 0x02E3F8 }, + { (char*) "America/North_Dakota/New_Salem" , 0x02ED75 }, + { (char*) "America/Nuuk" , 0x02F6F8 }, + { (char*) "America/Ojinaga" , 0x02FE76 }, + { (char*) "America/Panama" , 0x030492 }, + { (char*) "America/Pangnirtung" , 0x030554 }, + { (char*) "America/Paramaribo" , 0x030DFA }, + { (char*) "America/Phoenix" , 0x030EFE }, + { (char*) "America/Port-au-Prince" , 0x03108A }, + { (char*) "America/Port_of_Spain" , 0x031630 }, + { (char*) "America/Porto_Acre" , 0x0316D0 }, + { (char*) "America/Porto_Velho" , 0x031942 }, + { (char*) "America/Puerto_Rico" , 0x031B88 }, + { (char*) "America/Punta_Arenas" , 0x031C8A }, + { (char*) "America/Rainy_River" , 0x032415 }, + { (char*) "America/Rankin_Inlet" , 0x032F55 }, + { (char*) "America/Recife" , 0x033789 }, + { (char*) "America/Regina" , 0x033A5D }, + { (char*) "America/Resolute" , 0x033E52 }, + { (char*) "America/Rio_Branco" , 0x034687 }, + { (char*) "America/Rosario" , 0x0348FD }, + { (char*) "America/Santa_Isabel" , 0x034D2F }, + { (char*) "America/Santarem" , 0x0356D5 }, + { (char*) "America/Santiago" , 0x035938 }, + { (char*) "America/Santo_Domingo" , 0x036324 }, + { (char*) "America/Sao_Paulo" , 0x0364FA }, + { (char*) "America/Scoresbysund" , 0x036AD2 }, + { (char*) "America/Shiprock" , 0x03728A }, + { (char*) "America/Sitka" , 0x037C32 }, + { (char*) "America/St_Barthelemy" , 0x03856A }, + { (char*) "America/St_Johns" , 0x03866C }, + { (char*) "America/St_Kitts" , 0x0394DA }, + { (char*) "America/St_Lucia" , 0x03957A }, + { (char*) "America/St_Thomas" , 0x03963C }, + { (char*) "America/St_Vincent" , 0x0396DC }, + { (char*) "America/Swift_Current" , 0x03979E }, + { (char*) "America/Tegucigalpa" , 0x0399EC }, + { (char*) "America/Thule" , 0x039AF4 }, + { (char*) "America/Thunder_Bay" , 0x03A0EC }, + { (char*) "America/Tijuana" , 0x03AE9E }, + { (char*) "America/Toronto" , 0x03B853 }, + { (char*) "America/Tortola" , 0x03C623 }, + { (char*) "America/Vancouver" , 0x03C6C3 }, + { (char*) "America/Virgin" , 0x03D234 }, + { (char*) "America/Whitehorse" , 0x03D336 }, + { (char*) "America/Winnipeg" , 0x03D9A2 }, + { (char*) "America/Yakutat" , 0x03E4FF }, + { (char*) "America/Yellowknife" , 0x03EE1C }, + { (char*) "Antarctica/Casey" , 0x03F744 }, + { (char*) "Antarctica/Davis" , 0x03F8FC }, + { (char*) "Antarctica/DumontDUrville" , 0x03FA28 }, + { (char*) "Antarctica/Macquarie" , 0x03FAF8 }, + { (char*) "Antarctica/Mawson" , 0x0403E8 }, + { (char*) "Antarctica/McMurdo" , 0x0404B3 }, + { (char*) "Antarctica/Palmer" , 0x040CAE }, + { (char*) "Antarctica/Rothera" , 0x04123C }, + { (char*) "Antarctica/South_Pole" , 0x0412E5 }, + { (char*) "Antarctica/Syowa" , 0x041C76 }, + { (char*) "Antarctica/Troll" , 0x041D1E }, + { (char*) "Antarctica/Vostok" , 0x0421AB }, + { (char*) "Arctic/Longyearbyen" , 0x042292 }, + { (char*) "Asia/Aden" , 0x042B98 }, + { (char*) "Asia/Almaty" , 0x042C3B }, + { (char*) "Asia/Amman" , 0x043030 }, + { (char*) "Asia/Anadyr" , 0x0435D5 }, + { (char*) "Asia/Aqtau" , 0x043A8A }, + { (char*) "Asia/Aqtobe" , 0x043E74 }, + { (char*) "Asia/Ashgabat" , 0x044272 }, + { (char*) "Asia/Ashkhabad" , 0x0444DB }, + { (char*) "Asia/Atyrau" , 0x044744 }, + { (char*) "Asia/Baghdad" , 0x044B36 }, + { (char*) "Asia/Bahrain" , 0x044F0B }, + { (char*) "Asia/Baku" , 0x044FF6 }, + { (char*) "Asia/Bangkok" , 0x0454BF }, + { (char*) "Asia/Barnaul" , 0x045584 }, + { (char*) "Asia/Beirut" , 0x045A55 }, + { (char*) "Asia/Bishkek" , 0x0462CB }, + { (char*) "Asia/Brunei" , 0x0466A0 }, + { (char*) "Asia/Calcutta" , 0x046769 }, + { (char*) "Asia/Chita" , 0x046892 }, + { (char*) "Asia/Choibalsan" , 0x046D69 }, + { (char*) "Asia/Chongqing" , 0x0470E2 }, + { (char*) "Asia/Chungking" , 0x04731F }, + { (char*) "Asia/Colombo" , 0x04755C }, + { (char*) "Asia/Dacca" , 0x0476CE }, + { (char*) "Asia/Damascus" , 0x04781D }, + { (char*) "Asia/Dhaka" , 0x047F7A }, + { (char*) "Asia/Dili" , 0x0480C9 }, + { (char*) "Asia/Dubai" , 0x0481D6 }, + { (char*) "Asia/Dushanbe" , 0x048279 }, + { (char*) "Asia/Famagusta" , 0x0484C6 }, + { (char*) "Asia/Gaza" , 0x048CCD }, + { (char*) "Asia/Harbin" , 0x049BE7 }, + { (char*) "Asia/Hebron" , 0x049E24 }, + { (char*) "Asia/Ho_Chi_Minh" , 0x04AD59 }, + { (char*) "Asia/Hong_Kong" , 0x04AEB6 }, + { (char*) "Asia/Hovd" , 0x04B393 }, + { (char*) "Asia/Irkutsk" , 0x04B722 }, + { (char*) "Asia/Istanbul" , 0x04BC15 }, + { (char*) "Asia/Jakarta" , 0x04C3AE }, + { (char*) "Asia/Jayapura" , 0x04C546 }, + { (char*) "Asia/Jerusalem" , 0x04C665 }, + { (char*) "Asia/Kabul" , 0x04CFC5 }, + { (char*) "Asia/Kamchatka" , 0x04D093 }, + { (char*) "Asia/Karachi" , 0x04D531 }, + { (char*) "Asia/Kashgar" , 0x04D6B8 }, + { (char*) "Asia/Kathmandu" , 0x04D75B }, + { (char*) "Asia/Katmandu" , 0x04D82D }, + { (char*) "Asia/Khandyga" , 0x04D8FF }, + { (char*) "Asia/Kolkata" , 0x04DE12 }, + { (char*) "Asia/Krasnoyarsk" , 0x04DF3B }, + { (char*) "Asia/Kuala_Lumpur" , 0x04E409 }, + { (char*) "Asia/Kuching" , 0x04E5BA }, + { (char*) "Asia/Kuwait" , 0x04E7A9 }, + { (char*) "Asia/Macao" , 0x04E84C }, + { (char*) "Asia/Macau" , 0x04ED23 }, + { (char*) "Asia/Magadan" , 0x04F1FA }, + { (char*) "Asia/Makassar" , 0x04F6CE }, + { (char*) "Asia/Manila" , 0x04F821 }, + { (char*) "Asia/Muscat" , 0x04F9D3 }, + { (char*) "Asia/Nicosia" , 0x04FA76 }, + { (char*) "Asia/Novokuznetsk" , 0x050262 }, + { (char*) "Asia/Novosibirsk" , 0x0506FE }, + { (char*) "Asia/Omsk" , 0x050BD5 }, + { (char*) "Asia/Oral" , 0x051097 }, + { (char*) "Asia/Phnom_Penh" , 0x051491 }, + { (char*) "Asia/Pontianak" , 0x0515B6 }, + { (char*) "Asia/Pyongyang" , 0x051739 }, + { (char*) "Asia/Qatar" , 0x051832 }, + { (char*) "Asia/Qostanay" , 0x0518F7 }, + { (char*) "Asia/Qyzylorda" , 0x051D1E }, + { (char*) "Asia/Rangoon" , 0x05213A }, + { (char*) "Asia/Riyadh" , 0x052244 }, + { (char*) "Asia/Saigon" , 0x0522E7 }, + { (char*) "Asia/Sakhalin" , 0x052444 }, + { (char*) "Asia/Samarkand" , 0x05290C }, + { (char*) "Asia/Seoul" , 0x052B5C }, + { (char*) "Asia/Shanghai" , 0x052DD1 }, + { (char*) "Asia/Singapore" , 0x05301A }, + { (char*) "Asia/Srednekolymsk" , 0x0531B7 }, + { (char*) "Asia/Taipei" , 0x05368B }, + { (char*) "Asia/Tashkent" , 0x053990 }, + { (char*) "Asia/Tbilisi" , 0x053BEE }, + { (char*) "Asia/Tehran" , 0x053FF7 }, + { (char*) "Asia/Tel_Aviv" , 0x0544E3 }, + { (char*) "Asia/Thimbu" , 0x054E43 }, + { (char*) "Asia/Thimphu" , 0x054F0C }, + { (char*) "Asia/Tokyo" , 0x054FD5 }, + { (char*) "Asia/Tomsk" , 0x055116 }, + { (char*) "Asia/Ujung_Pandang" , 0x0555E7 }, + { (char*) "Asia/Ulaanbaatar" , 0x0556F1 }, + { (char*) "Asia/Ulan_Bator" , 0x055A7A }, + { (char*) "Asia/Urumqi" , 0x055DF3 }, + { (char*) "Asia/Ust-Nera" , 0x055EA3 }, + { (char*) "Asia/Vientiane" , 0x056399 }, + { (char*) "Asia/Vladivostok" , 0x0564DA }, + { (char*) "Asia/Yakutsk" , 0x0569A3 }, + { (char*) "Asia/Yangon" , 0x056E6B }, + { (char*) "Asia/Yekaterinburg" , 0x056F75 }, + { (char*) "Asia/Yerevan" , 0x05745C }, + { (char*) "Atlantic/Azores" , 0x0578D9 }, + { (char*) "Atlantic/Bermuda" , 0x05865D }, + { (char*) "Atlantic/Canary" , 0x058FC5 }, + { (char*) "Atlantic/Cape_Verde" , 0x059748 }, + { (char*) "Atlantic/Faeroe" , 0x059854 }, + { (char*) "Atlantic/Faroe" , 0x059F77 }, + { (char*) "Atlantic/Jan_Mayen" , 0x05A69A }, + { (char*) "Atlantic/Madeira" , 0x05AFA0 }, + { (char*) "Atlantic/Reykjavik" , 0x05BCEC }, + { (char*) "Atlantic/South_Georgia" , 0x05C182 }, + { (char*) "Atlantic/St_Helena" , 0x05C224 }, + { (char*) "Atlantic/Stanley" , 0x05C2E6 }, + { (char*) "Australia/ACT" , 0x05C7A2 }, + { (char*) "Australia/Adelaide" , 0x05D03C }, + { (char*) "Australia/Brisbane" , 0x05D8F7 }, + { (char*) "Australia/Broken_Hill" , 0x05DABD }, + { (char*) "Australia/Canberra" , 0x05E39A }, + { (char*) "Australia/Currie" , 0x05EC34 }, + { (char*) "Australia/Darwin" , 0x05F576 }, + { (char*) "Australia/Eucla" , 0x05F6D9 }, + { (char*) "Australia/Hobart" , 0x05F8C6 }, + { (char*) "Australia/LHI" , 0x060210 }, + { (char*) "Australia/Lindeman" , 0x060952 }, + { (char*) "Australia/Lord_Howe" , 0x060B58 }, + { (char*) "Australia/Melbourne" , 0x0612AA }, + { (char*) "Australia/North" , 0x061B4C }, + { (char*) "Australia/NSW" , 0x061C9D }, + { (char*) "Australia/Perth" , 0x062537 }, + { (char*) "Australia/Queensland" , 0x06271F }, + { (char*) "Australia/South" , 0x0628CE }, + { (char*) "Australia/Sydney" , 0x06317A }, + { (char*) "Australia/Tasmania" , 0x063A30 }, + { (char*) "Australia/Victoria" , 0x064372 }, + { (char*) "Australia/West" , 0x064C0C }, + { (char*) "Australia/Yancowinna" , 0x064DD6 }, + { (char*) "Brazil/Acre" , 0x065697 }, + { (char*) "Brazil/DeNoronha" , 0x065909 }, + { (char*) "Brazil/East" , 0x065BD3 }, + { (char*) "Brazil/West" , 0x066175 }, + { (char*) "Canada/Atlantic" , 0x0663CF }, + { (char*) "Canada/Central" , 0x06713B }, + { (char*) "Canada/Eastern" , 0x067C7B }, + { (char*) "Canada/Mountain" , 0x068A2D }, + { (char*) "Canada/Newfoundland" , 0x069355 }, + { (char*) "Canada/Pacific" , 0x06A1A8 }, + { (char*) "Canada/Saskatchewan" , 0x06AD00 }, + { (char*) "Canada/Yukon" , 0x06B0E0 }, + { (char*) "CET" , 0x06B73A }, + { (char*) "Chile/Continental" , 0x06C2BB }, + { (char*) "Chile/EasterIsland" , 0x06CC9A }, + { (char*) "CST6CDT" , 0x06D551 }, + { (char*) "Cuba" , 0x06E365 }, + { (char*) "EET" , 0x06ECE1 }, + { (char*) "Egypt" , 0x06F5C3 }, + { (char*) "Eire" , 0x06FF2E }, + { (char*) "EST" , 0x070CDE }, + { (char*) "EST5EDT" , 0x070DA0 }, + { (char*) "Etc/GMT" , 0x071B8C }, + { (char*) "Etc/GMT+0" , 0x071C0A }, + { (char*) "Etc/GMT+1" , 0x071C88 }, + { (char*) "Etc/GMT+10" , 0x071D08 }, + { (char*) "Etc/GMT+11" , 0x071D89 }, + { (char*) "Etc/GMT+12" , 0x071E0A }, + { (char*) "Etc/GMT+2" , 0x071E8B }, + { (char*) "Etc/GMT+3" , 0x071F0B }, + { (char*) "Etc/GMT+4" , 0x071F8B }, + { (char*) "Etc/GMT+5" , 0x07200B }, + { (char*) "Etc/GMT+6" , 0x07208B }, + { (char*) "Etc/GMT+7" , 0x07210B }, + { (char*) "Etc/GMT+8" , 0x07218B }, + { (char*) "Etc/GMT+9" , 0x07220B }, + { (char*) "Etc/GMT-0" , 0x07228B }, + { (char*) "Etc/GMT-1" , 0x072309 }, + { (char*) "Etc/GMT-10" , 0x07238A }, + { (char*) "Etc/GMT-11" , 0x07240C }, + { (char*) "Etc/GMT-12" , 0x07248E }, + { (char*) "Etc/GMT-13" , 0x072510 }, + { (char*) "Etc/GMT-14" , 0x072592 }, + { (char*) "Etc/GMT-2" , 0x072614 }, + { (char*) "Etc/GMT-3" , 0x072695 }, + { (char*) "Etc/GMT-4" , 0x072716 }, + { (char*) "Etc/GMT-5" , 0x072797 }, + { (char*) "Etc/GMT-6" , 0x072818 }, + { (char*) "Etc/GMT-7" , 0x072899 }, + { (char*) "Etc/GMT-8" , 0x07291A }, + { (char*) "Etc/GMT-9" , 0x07299B }, + { (char*) "Etc/GMT0" , 0x072A1C }, + { (char*) "Etc/Greenwich" , 0x072A9A }, + { (char*) "Etc/UCT" , 0x072B18 }, + { (char*) "Etc/Universal" , 0x072B96 }, + { (char*) "Etc/UTC" , 0x072C14 }, + { (char*) "Etc/Zulu" , 0x072C92 }, + { (char*) "Europe/Amsterdam" , 0x072D10 }, + { (char*) "Europe/Andorra" , 0x07387A }, + { (char*) "Europe/Astrakhan" , 0x073F54 }, + { (char*) "Europe/Athens" , 0x0743F1 }, + { (char*) "Europe/Belfast" , 0x074CD3 }, + { (char*) "Europe/Belgrade" , 0x075B2F }, + { (char*) "Europe/Berlin" , 0x0762BB }, + { (char*) "Europe/Bratislava" , 0x076BD0 }, + { (char*) "Europe/Brussels" , 0x0774D9 }, + { (char*) "Europe/Bucharest" , 0x07805A }, + { (char*) "Europe/Budapest" , 0x0788EE }, + { (char*) "Europe/Busingen" , 0x07923A }, + { (char*) "Europe/Chisinau" , 0x0799C3 }, + { (char*) "Europe/Copenhagen" , 0x07A325 }, + { (char*) "Europe/Dublin" , 0x07AB8A }, + { (char*) "Europe/Gibraltar" , 0x07B93A }, + { (char*) "Europe/Guernsey" , 0x07C542 }, + { (char*) "Europe/Helsinki" , 0x07D3E2 }, + { (char*) "Europe/Isle_of_Man" , 0x07DB5A }, + { (char*) "Europe/Istanbul" , 0x07E9A6 }, + { (char*) "Europe/Jersey" , 0x07F13F }, + { (char*) "Europe/Kaliningrad" , 0x07FFDF }, + { (char*) "Europe/Kiev" , 0x0805D4 }, + { (char*) "Europe/Kirov" , 0x080E28 }, + { (char*) "Europe/Kyiv" , 0x0812E3 }, + { (char*) "Europe/Lisbon" , 0x081B46 }, + { (char*) "Europe/Ljubljana" , 0x08292C }, + { (char*) "Europe/London" , 0x0830B8 }, + { (char*) "Europe/Luxembourg" , 0x083F14 }, + { (char*) "Europe/Madrid" , 0x084AA2 }, + { (char*) "Europe/Malta" , 0x0854F4 }, + { (char*) "Europe/Mariehamn" , 0x085F3C }, + { (char*) "Europe/Minsk" , 0x0866B4 }, + { (char*) "Europe/Monaco" , 0x086BDB }, + { (char*) "Europe/Moscow" , 0x087767 }, + { (char*) "Europe/Nicosia" , 0x087D86 }, + { (char*) "Europe/Oslo" , 0x088564 }, + { (char*) "Europe/Paris" , 0x088E24 }, + { (char*) "Europe/Podgorica" , 0x0899C2 }, + { (char*) "Europe/Prague" , 0x08A14E }, + { (char*) "Europe/Riga" , 0x08AA57 }, + { (char*) "Europe/Rome" , 0x08B2F9 }, + { (char*) "Europe/Samara" , 0x08BD56 }, + { (char*) "Europe/San_Marino" , 0x08C22C }, + { (char*) "Europe/Sarajevo" , 0x08CC89 }, + { (char*) "Europe/Saratov" , 0x08D415 }, + { (char*) "Europe/Simferopol" , 0x08D8C2 }, + { (char*) "Europe/Skopje" , 0x08DE91 }, + { (char*) "Europe/Sofia" , 0x08E61D }, + { (char*) "Europe/Stockholm" , 0x08EE46 }, + { (char*) "Europe/Tallinn" , 0x08F5C7 }, + { (char*) "Europe/Tirane" , 0x08FE37 }, + { (char*) "Europe/Tiraspol" , 0x090667 }, + { (char*) "Europe/Ulyanovsk" , 0x090FC9 }, + { (char*) "Europe/Uzhgorod" , 0x0914CC }, + { (char*) "Europe/Vaduz" , 0x091D20 }, + { (char*) "Europe/Vatican" , 0x09248C }, + { (char*) "Europe/Vienna" , 0x092EE9 }, + { (char*) "Europe/Vilnius" , 0x09378D }, + { (char*) "Europe/Volgograd" , 0x09400B }, + { (char*) "Europe/Warsaw" , 0x0944D2 }, + { (char*) "Europe/Zagreb" , 0x094F3C }, + { (char*) "Europe/Zaporozhye" , 0x0956C8 }, + { (char*) "Europe/Zurich" , 0x095F1C }, + { (char*) "Factory" , 0x09669D }, + { (char*) "GB" , 0x09671D }, + { (char*) "GB-Eire" , 0x097579 }, + { (char*) "GMT" , 0x0983D5 }, + { (char*) "GMT+0" , 0x098453 }, + { (char*) "GMT-0" , 0x0984D1 }, + { (char*) "GMT0" , 0x09854F }, + { (char*) "Greenwich" , 0x0985CD }, + { (char*) "Hongkong" , 0x09864B }, + { (char*) "HST" , 0x098B28 }, + { (char*) "Iceland" , 0x098C7D }, + { (char*) "Indian/Antananarivo" , 0x098D1D }, + { (char*) "Indian/Chagos" , 0x098E04 }, + { (char*) "Indian/Christmas" , 0x098EC9 }, + { (char*) "Indian/Cocos" , 0x098F6C }, + { (char*) "Indian/Comoro" , 0x099018 }, + { (char*) "Indian/Kerguelen" , 0x0990B9 }, + { (char*) "Indian/Mahe" , 0x09915C }, + { (char*) "Indian/Maldives" , 0x0991FF }, + { (char*) "Indian/Mauritius" , 0x0992C4 }, + { (char*) "Indian/Mayotte" , 0x0993B3 }, + { (char*) "Indian/Reunion" , 0x099454 }, + { (char*) "Iran" , 0x0994F7 }, + { (char*) "Israel" , 0x0999E3 }, + { (char*) "Jamaica" , 0x09A343 }, + { (char*) "Japan" , 0x09A531 }, + { (char*) "Kwajalein" , 0x09A672 }, + { (char*) "Libya" , 0x09A7AC }, + { (char*) "MET" , 0x09AA29 }, + { (char*) "Mexico/BajaNorte" , 0x09B5AA }, + { (char*) "Mexico/BajaSur" , 0x09BF50 }, + { (char*) "Mexico/General" , 0x09C380 }, + { (char*) "MST" , 0x09C852 }, + { (char*) "MST7MDT" , 0x09C9C6 }, + { (char*) "Navajo" , 0x09D36E }, + { (char*) "NZ" , 0x09DD16 }, + { (char*) "NZ-CHAT" , 0x09E6A7 }, + { (char*) "Pacific/Apia" , 0x09EEB9 }, + { (char*) "Pacific/Auckland" , 0x09F11B }, + { (char*) "Pacific/Bougainville" , 0x09FABF }, + { (char*) "Pacific/Chatham" , 0x09FBD5 }, + { (char*) "Pacific/Chuuk" , 0x0A03F6 }, + { (char*) "Pacific/Easter" , 0x0A0510 }, + { (char*) "Pacific/Efate" , 0x0A0DD4 }, + { (char*) "Pacific/Enderbury" , 0x0A0FEC }, + { (char*) "Pacific/Fakaofo" , 0x0A10D4 }, + { (char*) "Pacific/Fiji" , 0x0A119A }, + { (char*) "Pacific/Funafuti" , 0x0A13DA }, + { (char*) "Pacific/Galapagos" , 0x0A147E }, + { (char*) "Pacific/Gambier" , 0x0A157B }, + { (char*) "Pacific/Guadalcanal" , 0x0A162C }, + { (char*) "Pacific/Guam" , 0x0A16D0 }, + { (char*) "Pacific/Honolulu" , 0x0A18CA }, + { (char*) "Pacific/Johnston" , 0x0A1A25 }, + { (char*) "Pacific/Kanton" , 0x0A1B7A }, + { (char*) "Pacific/Kiritimati" , 0x0A1C71 }, + { (char*) "Pacific/Kosrae" , 0x0A1D69 }, + { (char*) "Pacific/Kwajalein" , 0x0A1ECC }, + { (char*) "Pacific/Majuro" , 0x0A200F }, + { (char*) "Pacific/Marquesas" , 0x0A215B }, + { (char*) "Pacific/Midway" , 0x0A2217 }, + { (char*) "Pacific/Nauru" , 0x0A230A }, + { (char*) "Pacific/Niue" , 0x0A2404 }, + { (char*) "Pacific/Norfolk" , 0x0A24CD }, + { (char*) "Pacific/Noumea" , 0x0A283B }, + { (char*) "Pacific/Pago_Pago" , 0x0A2969 }, + { (char*) "Pacific/Palau" , 0x0A2A24 }, + { (char*) "Pacific/Pitcairn" , 0x0A2AD6 }, + { (char*) "Pacific/Pohnpei" , 0x0A2B9E }, + { (char*) "Pacific/Ponape" , 0x0A2CD9 }, + { (char*) "Pacific/Port_Moresby" , 0x0A2D7D }, + { (char*) "Pacific/Rarotonga" , 0x0A2E4D }, + { (char*) "Pacific/Saipan" , 0x0A30A6 }, + { (char*) "Pacific/Samoa" , 0x0A3292 }, + { (char*) "Pacific/Tahiti" , 0x0A334D }, + { (char*) "Pacific/Tarawa" , 0x0A33FF }, + { (char*) "Pacific/Tongatapu" , 0x0A34B2 }, + { (char*) "Pacific/Truk" , 0x0A3624 }, + { (char*) "Pacific/Wake" , 0x0A36DC }, + { (char*) "Pacific/Wallis" , 0x0A378B }, + { (char*) "Pacific/Yap" , 0x0A382F }, + { (char*) "Poland" , 0x0A38E7 }, + { (char*) "Portugal" , 0x0A4351 }, + { (char*) "PRC" , 0x0A5124 }, + { (char*) "PST8PDT" , 0x0A5361 }, + { (char*) "ROC" , 0x0A5E91 }, + { (char*) "ROK" , 0x0A6196 }, + { (char*) "Singapore" , 0x0A640B }, + { (char*) "Turkey" , 0x0A65A8 }, + { (char*) "UCT" , 0x0A6D41 }, + { (char*) "Universal" , 0x0A6DBF }, + { (char*) "US/Alaska" , 0x0A6E3D }, + { (char*) "US/Aleutian" , 0x0A778C }, + { (char*) "US/Arizona" , 0x0A80CC }, + { (char*) "US/Central" , 0x0A8240 }, + { (char*) "US/East-Indiana" , 0x0A9054 }, + { (char*) "US/Eastern" , 0x0A96F2 }, + { (char*) "US/Hawaii" , 0x0AA4DE }, + { (char*) "US/Indiana-Starke" , 0x0AA633 }, + { (char*) "US/Michigan" , 0x0AAFCB }, + { (char*) "US/Mountain" , 0x0AB88D }, + { (char*) "US/Pacific" , 0x0AC235 }, + { (char*) "US/Samoa" , 0x0ACD65 }, + { (char*) "UTC" , 0x0ACE20 }, + { (char*) "W-SU" , 0x0ACE9E }, + { (char*) "WET" , 0x0AD4A9 }, + { (char*) "Zulu" , 0x0AE27C }, }; -const unsigned char timelib_timezone_db_data_builtin[711319] = { +const unsigned char timelib_timezone_db_data_builtin[713466] = { /* Africa/Abidjan */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -29630,6 +29720,143 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x54, 0x00, 0x43, 0x53, 0x54, 0x00, 0x0A, 0x43, 0x53, 0x54, 0x36, 0x0A, 0x00, 0x98, 0x7C, 0x75, 0x00, 0x92, 0x5B, 0x72, 0x00, 0x00, 0x00, 0x00, +/* America/Coyhaique */ +0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, +0x8F, 0x30, 0x47, 0x45, 0x9B, 0x5C, 0xE5, 0x50, 0x9F, 0x7C, 0xE2, 0xC5, 0xA1, 0x00, 0x71, 0xC0, +0xB0, 0x5E, 0x77, 0xC5, 0xB1, 0x77, 0x3D, 0x40, 0xB2, 0x41, 0x00, 0xD0, 0xB3, 0x58, 0x70, 0xC0, +0xB4, 0x22, 0x34, 0x50, 0xB5, 0x39, 0xA4, 0x40, 0xB6, 0x03, 0x67, 0xD0, 0xB7, 0x1A, 0xD7, 0xC0, +0xB7, 0xE4, 0x9B, 0x50, 0xB8, 0xFD, 0x5C, 0xC0, 0xB9, 0xC7, 0x20, 0x50, 0xCC, 0x1C, 0x6E, 0x40, +0xCC, 0x6C, 0xE7, 0xD0, 0xD4, 0x17, 0xE3, 0x40, 0xD5, 0x33, 0x55, 0xC0, 0xD5, 0x76, 0x92, 0x40, +0xFD, 0xD1, 0x3C, 0x40, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x72, 0xDC, 0xB0, +0x01, 0x75, 0x50, 0xC0, 0x02, 0x40, 0x49, 0xB0, 0x03, 0x55, 0x32, 0xC0, 0x04, 0x20, 0x2B, 0xB0, +0x05, 0x3E, 0x4F, 0x40, 0x06, 0x00, 0x0D, 0xB0, 0x07, 0x0B, 0xBC, 0x40, 0x07, 0xDF, 0xEF, 0xB0, +0x08, 0xFE, 0x13, 0x40, 0x09, 0xBF, 0xD1, 0xB0, 0x0A, 0xDD, 0xF5, 0x40, 0x0B, 0xA8, 0xEE, 0x30, +0x0C, 0xBD, 0xD7, 0x40, 0x0D, 0x88, 0xD0, 0x30, 0x0E, 0x9D, 0xB9, 0x40, 0x0F, 0x68, 0xB2, 0x30, +0x10, 0x86, 0xD5, 0xC0, 0x11, 0x48, 0x94, 0x30, 0x12, 0x66, 0xB7, 0xC0, 0x13, 0x28, 0x76, 0x30, +0x14, 0x46, 0x99, 0xC0, 0x15, 0x11, 0x92, 0xB0, 0x16, 0x26, 0x7B, 0xC0, 0x16, 0xF1, 0x74, 0xB0, +0x18, 0x06, 0x5D, 0xC0, 0x18, 0xD1, 0x56, 0xB0, 0x19, 0xE6, 0x3F, 0xC0, 0x1A, 0xB1, 0x38, 0xB0, +0x1B, 0xCF, 0x5C, 0x40, 0x1C, 0x91, 0x1A, 0xB0, 0x1D, 0xAF, 0x3E, 0x40, 0x1E, 0x70, 0xFC, 0xB0, +0x1F, 0x8F, 0x20, 0x40, 0x20, 0x7F, 0x03, 0x30, 0x21, 0x6F, 0x02, 0x40, 0x22, 0x39, 0xFB, 0x30, +0x23, 0x4E, 0xE4, 0x40, 0x24, 0x19, 0xDD, 0x30, 0x25, 0x38, 0x00, 0xC0, 0x25, 0xF9, 0xBF, 0x30, +0x26, 0xF2, 0xF8, 0xC0, 0x27, 0xD9, 0xA1, 0x30, 0x28, 0xF7, 0xC4, 0xC0, 0x29, 0xC2, 0xBD, 0xB0, +0x2A, 0xD7, 0xA6, 0xC0, 0x2B, 0xA2, 0x9F, 0xB0, 0x2C, 0xB7, 0x88, 0xC0, 0x2D, 0x82, 0x81, 0xB0, +0x2E, 0x97, 0x6A, 0xC0, 0x2F, 0x62, 0x63, 0xB0, 0x30, 0x80, 0x87, 0x40, 0x31, 0x42, 0x45, 0xB0, +0x32, 0x60, 0x69, 0x40, 0x33, 0x3D, 0xD7, 0x30, 0x34, 0x40, 0x4B, 0x40, 0x35, 0x0B, 0x44, 0x30, +0x36, 0x0D, 0xB8, 0x40, 0x37, 0x06, 0xD5, 0xB0, 0x38, 0x00, 0x0F, 0x40, 0x38, 0xCB, 0x08, 0x30, +0x39, 0xE9, 0x2B, 0xC0, 0x3A, 0xAA, 0xEA, 0x30, 0x3B, 0xC9, 0x0D, 0xC0, 0x3C, 0x8A, 0xCC, 0x30, +0x3D, 0xA8, 0xEF, 0xC0, 0x3E, 0x6A, 0xAE, 0x30, 0x3F, 0x88, 0xD1, 0xC0, 0x40, 0x53, 0xCA, 0xB0, +0x41, 0x68, 0xB3, 0xC0, 0x42, 0x33, 0xAC, 0xB0, 0x43, 0x48, 0x95, 0xC0, 0x44, 0x13, 0x8E, 0xB0, +0x45, 0x31, 0xB2, 0x40, 0x45, 0xF3, 0x70, 0xB0, 0x47, 0x11, 0x94, 0x40, 0x47, 0xEF, 0x02, 0x30, +0x48, 0xF1, 0x76, 0x40, 0x49, 0xBC, 0x6F, 0x30, 0x4A, 0xD1, 0x58, 0x40, 0x4B, 0xB8, 0x00, 0xB0, +0x4C, 0xB1, 0x3A, 0x40, 0x4D, 0xC6, 0x07, 0x30, 0x4E, 0x50, 0x82, 0xC0, 0x4F, 0x9C, 0xAE, 0xB0, +0x50, 0x42, 0xD9, 0xC0, 0x51, 0x7C, 0x90, 0xB0, 0x52, 0x2B, 0xF6, 0x40, 0x53, 0x5C, 0x72, 0xB0, +0x54, 0x0B, 0xD8, 0x40, 0x57, 0x37, 0xE6, 0x30, 0x57, 0xAF, 0xEC, 0xC0, 0x59, 0x17, 0xC8, 0x30, +0x59, 0x8F, 0xCE, 0xC0, 0x5A, 0xF7, 0xAA, 0x30, 0x5B, 0x6F, 0xB0, 0xC0, 0x5C, 0xA9, 0x67, 0xB0, +0x5D, 0x74, 0x7C, 0xC0, 0x5E, 0x89, 0x49, 0xB0, 0x5F, 0x54, 0x5E, 0xC0, 0x60, 0x69, 0x2B, 0xB0, +0x61, 0x34, 0x40, 0xC0, 0x62, 0x49, 0x0D, 0xB0, 0x63, 0x1D, 0x5D, 0x40, 0x64, 0x28, 0xEF, 0xB0, +0x64, 0xF4, 0x04, 0xC0, 0x66, 0x12, 0x0C, 0x30, 0x66, 0xDD, 0x21, 0x40, 0x67, 0xDB, 0x84, 0xB0, +0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, +0x02, 0x03, 0x04, 0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, +0x06, 0x05, 0x06, 0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, +0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, +0xC0, 0x01, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, +0xFF, 0xD5, 0xD0, 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, +0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, +0x08, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x1F, 0x10, 0xFF, 0xFF, 0xFF, +0xFF, 0x8F, 0x30, 0x47, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x5C, 0xE5, 0x50, 0xFF, 0xFF, 0xFF, +0xFF, 0x9F, 0x7C, 0xE2, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x71, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB0, 0x5E, 0x77, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x77, 0x3D, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB2, 0x41, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB3, 0x58, 0x70, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB4, 0x22, 0x34, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0x39, 0xA4, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xB6, 0x03, 0x67, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x1A, 0xD7, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB7, 0xE4, 0x9B, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0xFD, 0x5C, 0xC0, 0xFF, 0xFF, 0xFF, +0xFF, 0xB9, 0xC7, 0x20, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x1C, 0x6E, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xCC, 0x6C, 0xE7, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x17, 0xE3, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xD5, 0x33, 0x55, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x76, 0x92, 0x40, 0xFF, 0xFF, 0xFF, +0xFF, 0xFD, 0xD1, 0x3C, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x92, 0xFA, 0xB0, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xCC, 0xCD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xDC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x01, 0x75, 0x50, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x03, 0x55, 0x32, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x05, 0x3E, 0x4F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x07, 0x0B, 0xBC, 0x40, 0x00, 0x00, 0x00, 0x00, 0x07, 0xDF, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x08, 0xFE, 0x13, 0x40, 0x00, 0x00, 0x00, 0x00, 0x09, 0xBF, 0xD1, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x0A, 0xDD, 0xF5, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xA8, 0xEE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0C, 0xBD, 0xD7, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x88, 0xD0, 0x30, 0x00, 0x00, 0x00, +0x00, 0x0E, 0x9D, 0xB9, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x68, 0xB2, 0x30, 0x00, 0x00, 0x00, +0x00, 0x10, 0x86, 0xD5, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0x48, 0x94, 0x30, 0x00, 0x00, 0x00, +0x00, 0x12, 0x66, 0xB7, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x28, 0x76, 0x30, 0x00, 0x00, 0x00, +0x00, 0x14, 0x46, 0x99, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x92, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x16, 0x26, 0x7B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x16, 0xF1, 0x74, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x18, 0x06, 0x5D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x18, 0xD1, 0x56, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x19, 0xE6, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xB1, 0x38, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1B, 0xCF, 0x5C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x91, 0x1A, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1D, 0xAF, 0x3E, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x70, 0xFC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x1F, 0x8F, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7F, 0x03, 0x30, 0x00, 0x00, 0x00, +0x00, 0x21, 0x6F, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x22, 0x39, 0xFB, 0x30, 0x00, 0x00, 0x00, +0x00, 0x23, 0x4E, 0xE4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x24, 0x19, 0xDD, 0x30, 0x00, 0x00, 0x00, +0x00, 0x25, 0x38, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF9, 0xBF, 0x30, 0x00, 0x00, 0x00, +0x00, 0x26, 0xF2, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x27, 0xD9, 0xA1, 0x30, 0x00, 0x00, 0x00, +0x00, 0x28, 0xF7, 0xC4, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xC2, 0xBD, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2A, 0xD7, 0xA6, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2B, 0xA2, 0x9F, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2C, 0xB7, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x82, 0x81, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x2E, 0x97, 0x6A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x62, 0x63, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x30, 0x80, 0x87, 0x40, 0x00, 0x00, 0x00, 0x00, 0x31, 0x42, 0x45, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x32, 0x60, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x33, 0x3D, 0xD7, 0x30, 0x00, 0x00, 0x00, +0x00, 0x34, 0x40, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x35, 0x0B, 0x44, 0x30, 0x00, 0x00, 0x00, +0x00, 0x36, 0x0D, 0xB8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x37, 0x06, 0xD5, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x38, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x38, 0xCB, 0x08, 0x30, 0x00, 0x00, 0x00, +0x00, 0x39, 0xE9, 0x2B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xAA, 0xEA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3B, 0xC9, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x8A, 0xCC, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3D, 0xA8, 0xEF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6A, 0xAE, 0x30, 0x00, 0x00, 0x00, +0x00, 0x3F, 0x88, 0xD1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xCA, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x41, 0x68, 0xB3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x33, 0xAC, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x43, 0x48, 0x95, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x44, 0x13, 0x8E, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x45, 0x31, 0xB2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF3, 0x70, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x47, 0x11, 0x94, 0x40, 0x00, 0x00, 0x00, 0x00, 0x47, 0xEF, 0x02, 0x30, 0x00, 0x00, 0x00, +0x00, 0x48, 0xF1, 0x76, 0x40, 0x00, 0x00, 0x00, 0x00, 0x49, 0xBC, 0x6F, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4A, 0xD1, 0x58, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xB8, 0x00, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x4C, 0xB1, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xC6, 0x07, 0x30, 0x00, 0x00, 0x00, +0x00, 0x4E, 0x50, 0x82, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x9C, 0xAE, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x50, 0x42, 0xD9, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x51, 0x7C, 0x90, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x52, 0x2B, 0xF6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x53, 0x5C, 0x72, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x54, 0x0B, 0xD8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x57, 0x37, 0xE6, 0x30, 0x00, 0x00, 0x00, +0x00, 0x57, 0xAF, 0xEC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x59, 0x17, 0xC8, 0x30, 0x00, 0x00, 0x00, +0x00, 0x59, 0x8F, 0xCE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xF7, 0xAA, 0x30, 0x00, 0x00, 0x00, +0x00, 0x5B, 0x6F, 0xB0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA9, 0x67, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5D, 0x74, 0x7C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x89, 0x49, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x5F, 0x54, 0x5E, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x69, 0x2B, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x61, 0x34, 0x40, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x62, 0x49, 0x0D, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x63, 0x1D, 0x5D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0xEF, 0xB0, 0x00, 0x00, 0x00, +0x00, 0x64, 0xF4, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x66, 0x12, 0x0C, 0x30, 0x00, 0x00, 0x00, +0x00, 0x66, 0xDD, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x67, 0xDB, 0x84, 0xB0, 0x01, 0x02, 0x01, +0x03, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x03, 0x02, 0x03, 0x04, +0x02, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x07, 0xFF, 0xFF, 0xBC, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xBD, 0xBB, 0x00, 0x04, 0xFF, 0xFF, +0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, +0xFF, 0xFF, 0xD5, 0xD0, 0x01, 0x10, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x0C, 0xFF, 0xFF, 0xD5, 0xD0, +0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, +0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x43, +0xCC, 0xC5, 0x00, 0xA4, 0xB1, 0x75, 0x00, 0x00, 0x00, 0x0C, 0x41, 0x79, 0x73, 0x65, 0x6E, 0x20, +0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, + /* America/Creston */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -38062,8 +38289,8 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x53, 0x4D, 0x54, 0x00, 0x2D, 0x30, 0x35, 0x00, 0x2D, 0x30, 0x34, 0x00, 0x2D, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x3C, 0x2D, 0x30, 0x33, 0x3E, 0x33, 0x0A, 0x00, 0x38, -0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x14, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, -0x20, 0x6F, 0x66, 0x20, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, 0x61, 0x6E, 0x65, 0x73, +0x3A, 0x88, 0x00, 0xA6, 0x72, 0xAD, 0x00, 0x00, 0x00, 0x11, 0x4D, 0x61, 0x67, 0x61, 0x6C, 0x6C, +0x61, 0x6E, 0x65, 0x73, 0x20, 0x52, 0x65, 0x67, 0x69, 0x6F, 0x6E, /* America/Rainy_River */ 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -47037,7 +47264,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -47068,7 +47295,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -65285,7 +65512,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x9A, 0x6C, 0x7D, 0xC8, 0xBF, 0x00, 0xCC, 0x48, 0x0D, 0x94, 0x44, 0x38, 0x0E, 0xAD, 0x13, 0xB8, 0x0F, 0x79, 0x73, 0x40, -0x10, 0x28, 0xCA, 0xC0, 0x10, 0xED, 0x3A, 0x40, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, +0x10, 0x28, 0xCA, 0xC0, 0x10, 0xA9, 0xFD, 0xC0, 0x11, 0xAD, 0xBC, 0x48, 0x12, 0x45, 0x4A, 0xB8, 0x13, 0x37, 0xEC, 0xC8, 0x14, 0x2D, 0x15, 0xB8, 0x28, 0x20, 0x76, 0xC8, 0x28, 0xDB, 0x9D, 0xB8, 0x29, 0xCB, 0x9C, 0xC8, 0x2A, 0xBE, 0x22, 0xB8, 0x2B, 0xAC, 0xD0, 0x48, 0x2C, 0x9F, 0x56, 0x38, 0x2D, 0x8E, 0x03, 0xC8, 0x2E, 0x80, 0x89, 0xB8, 0x2F, 0x6F, 0x37, 0x48, 0x30, 0x61, 0xBD, 0x38, @@ -65316,7 +65543,7 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x94, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xAD, 0x13, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x79, 0x73, 0x40, 0x00, -0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x3A, 0x40, 0x00, +0x00, 0x00, 0x00, 0x10, 0x28, 0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA9, 0xFD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x11, 0xAD, 0xBC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x12, 0x45, 0x4A, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2D, 0x15, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x76, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x28, 0xDB, 0x9D, 0xB8, 0x00, @@ -70844,4 +71071,4 @@ const unsigned char timelib_timezone_db_data_builtin[711319] = { }; #endif -const timelib_tzdb timezonedb_builtin = { "2025.1", 597, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; +const timelib_tzdb timezonedb_builtin = { "2025.2", 598, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; From d4c548cf42b5158b9e15fede483a15af0fb92f04 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 24 Mar 2025 15:07:14 +0100 Subject: [PATCH 157/503] Backport intl test changes for ICU 77 See GH-18125 See 8823f89a3282f1a77c2416779f9b0136c213e9fb --- ext/intl/tests/locale_get_display_name8.phpt | 12 ++++++------ ext/intl/tests/locale_get_display_variant2.phpt | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/intl/tests/locale_get_display_name8.phpt b/ext/intl/tests/locale_get_display_name8.phpt index e8c1ed958ac1c..aa91ee4c3b8ca 100644 --- a/ext/intl/tests/locale_get_display_name8.phpt +++ b/ext/intl/tests/locale_get_display_name8.phpt @@ -112,9 +112,9 @@ disp_locale=fr : display_name=slovène #Italie, NEDIS_KIRTI# disp_locale=de : display_name=Slowenisch #Italien, NEDIS_KIRTI# ----------------- locale='sl_IT_nedis-a-kirti-x-xyz' -disp_locale=en : display_name=Slovenian #Italy, NEDIS_A_KIRTI_X_XYZ# -disp_locale=fr : display_name=slovène #Italie, NEDIS_A_KIRTI_X_XYZ# -disp_locale=de : display_name=Slowenisch #Italien, NEDIS_A_KIRTI_X_XYZ# +disp_locale=en : display_name=Slovenian #Italy, NEDIS_A_KIRTI(_X_XYZ)?# +disp_locale=fr : display_name=slovène #Italie, NEDIS_A_KIRTI(_X_XYZ)?# +disp_locale=de : display_name=Slowenisch #Italien, NEDIS_A_KIRTI(_X_XYZ)?# ----------------- locale='sl_IT_rozaj' disp_locale=en : display_name=Slovenian #Italy, Resian# @@ -317,9 +317,9 @@ disp_locale=fr : display_name=anglais #États-Unis, attribute=islamcal# disp_locale=de : display_name=Englisch #Vereinigte Staaten, attribute=islamcal# ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_name=Chinese #China(, A_MYEXT_X_PRIVATE)?, a=myext, Private-Use=private# -disp_locale=fr : display_name=chinois #Chine(, A_MYEXT_X_PRIVATE)?, a=myext, usage privé=private# -disp_locale=de : display_name=Chinesisch #China(, A_MYEXT_X_PRIVATE)?, a=myext, Privatnutzung=private# +disp_locale=en : display_name=Chinese #China(, A_MYEXT(_X_PRIVATE)?)?, a=myext, Private-Use=private# +disp_locale=fr : display_name=chinois #Chine(, A_MYEXT(_X_PRIVATE)?)?, a=myext, usage privé=private# +disp_locale=de : display_name=Chinesisch #China(, A_MYEXT(_X_PRIVATE)?)?, a=myext, Privatnutzung=private# ----------------- locale='en-a-myExt-b-another' disp_locale=en : display_name=English #(A_MYEXT_B_ANOTHER, )?a=myext, b=another# diff --git a/ext/intl/tests/locale_get_display_variant2.phpt b/ext/intl/tests/locale_get_display_variant2.phpt index e56154902dde9..8e815e8c4e52a 100644 --- a/ext/intl/tests/locale_get_display_variant2.phpt +++ b/ext/intl/tests/locale_get_display_variant2.phpt @@ -248,9 +248,9 @@ disp_locale=fr : display_variant= disp_locale=de : display_variant= ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_variant=(A_MYEXT_X_PRIVATE)? -disp_locale=fr : display_variant=(A_MYEXT_X_PRIVATE)? -disp_locale=de : display_variant=(A_MYEXT_X_PRIVATE)? +disp_locale=en : display_variant=(A_MYEXT(_X_PRIVATE)?)? +disp_locale=fr : display_variant=(A_MYEXT(_X_PRIVATE)?)? +disp_locale=de : display_variant=(A_MYEXT(_X_PRIVATE)?)? ----------------- locale='en-a-myExt-b-another' disp_locale=en : display_variant=((A_)?MYEXT_B_ANOTHER)? From 8779e2a6031b78bb0e3cac980410eb038b9932c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 18 Mar 2025 11:07:20 +0100 Subject: [PATCH 158/503] Add `(void)` cast RFC: https://wiki.php.net/rfc/marking_return_value_as_important --- Zend/Optimizer/block_pass.c | 4 +- Zend/Optimizer/dce.c | 3 +- Zend/tests/type_casts/cast_to_void.phpt | 47 +++++++++++++++++++ Zend/tests/type_casts/cast_to_void_ast.phpt | 18 +++++++ .../type_casts/cast_to_void_destructor.phpt | 30 ++++++++++++ .../type_casts/cast_to_void_statement.phpt | 11 +++++ Zend/zend_ast.c | 3 ++ Zend/zend_ast.h | 1 + Zend/zend_compile.c | 23 +++++++++ Zend/zend_compile.h | 1 + Zend/zend_language_parser.y | 2 + Zend/zend_language_scanner.l | 4 ++ ext/tokenizer/tokenizer_data.c | 1 + ext/tokenizer/tokenizer_data.stub.php | 5 ++ ext/tokenizer/tokenizer_data_arginfo.h | 3 +- 15 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/type_casts/cast_to_void.phpt create mode 100644 Zend/tests/type_casts/cast_to_void_ast.phpt create mode 100644 Zend/tests/type_casts/cast_to_void_destructor.phpt create mode 100644 Zend/tests/type_casts/cast_to_void_statement.phpt diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 6fcbd04f12af5..2b6d71c385457 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -274,7 +274,9 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array * If it's not local, then the other blocks successors must also eventually either FREE or consume the temporary, * hence removing the temporary is not safe in the general case, especially when other consumers are not FREE. * A FREE may not be removed without also removing the source's result, because otherwise that would cause a memory leak. */ - if (opline->op1_type == IS_TMP_VAR) { + if (opline->extended_value == ZEND_FREE_VOID_CAST) { + /* Keep the ZEND_FREE opcode alive. */ + } else if (opline->op1_type == IS_TMP_VAR) { src = VAR_SOURCE(opline->op1); if (src) { switch (src->opcode) { diff --git a/Zend/Optimizer/dce.c b/Zend/Optimizer/dce.c index 414abe01f96ac..a00fd8bc6ad30 100644 --- a/Zend/Optimizer/dce.c +++ b/Zend/Optimizer/dce.c @@ -80,7 +80,6 @@ static inline bool may_have_side_effects( case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_QM_ASSIGN: - case ZEND_FREE: case ZEND_FE_FREE: case ZEND_TYPE_CHECK: case ZEND_DEFINED: @@ -127,6 +126,8 @@ static inline bool may_have_side_effects( case ZEND_ARRAY_KEY_EXISTS: /* No side effects */ return 0; + case ZEND_FREE: + return opline->extended_value == ZEND_FREE_VOID_CAST; case ZEND_ADD_ARRAY_ELEMENT: /* TODO: We can't free two vars. Keep instruction alive. "$b"]; */ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && (opline->op2_type & (IS_VAR|IS_TMP_VAR))) { diff --git a/Zend/tests/type_casts/cast_to_void.phpt b/Zend/tests/type_casts/cast_to_void.phpt new file mode 100644 index 0000000000000..cdbcffad519c9 --- /dev/null +++ b/Zend/tests/type_casts/cast_to_void.phpt @@ -0,0 +1,47 @@ +--TEST-- +casting different variables to void +--FILE-- + +--EXPECTF-- +Done diff --git a/Zend/tests/type_casts/cast_to_void_ast.phpt b/Zend/tests/type_casts/cast_to_void_ast.phpt new file mode 100644 index 0000000000000..26911bddb7ebc --- /dev/null +++ b/Zend/tests/type_casts/cast_to_void_ast.phpt @@ -0,0 +1,18 @@ +--TEST-- +(void) is included in AST printing +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +assert(false && function () { + (void)somefunc(); +}) diff --git a/Zend/tests/type_casts/cast_to_void_destructor.phpt b/Zend/tests/type_casts/cast_to_void_destructor.phpt new file mode 100644 index 0000000000000..027e4b77e5dda --- /dev/null +++ b/Zend/tests/type_casts/cast_to_void_destructor.phpt @@ -0,0 +1,30 @@ +--TEST-- +casting to void destroys the value. +--FILE-- + +--EXPECT-- +Before +WithDestructor::__destruct +After diff --git a/Zend/tests/type_casts/cast_to_void_statement.phpt b/Zend/tests/type_casts/cast_to_void_statement.phpt new file mode 100644 index 0000000000000..3262e1efd549c --- /dev/null +++ b/Zend/tests/type_casts/cast_to_void_statement.phpt @@ -0,0 +1,11 @@ +--TEST-- +casting to void is a statement +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected token "(void)" in %s on line %d diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 8b0a66fda8096..1ae7a0ef7a68e 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -2261,6 +2261,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio EMPTY_SWITCH_DEFAULT_CASE(); } break; + case ZEND_AST_CAST_VOID: + PREFIX_OP("(void)", 240, 241); + break; case ZEND_AST_EMPTY: FUNC_OP("empty"); case ZEND_AST_ISSET: diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index d0dad8490c4e3..9348c35f6cc07 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -84,6 +84,7 @@ enum _zend_ast_kind { ZEND_AST_UNARY_PLUS, ZEND_AST_UNARY_MINUS, ZEND_AST_CAST, + ZEND_AST_CAST_VOID, ZEND_AST_EMPTY, ZEND_AST_ISSET, ZEND_AST_SILENCE, diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cd0ac6eb07b9c..1cba9ef221997 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -10589,6 +10589,26 @@ static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ +static void zend_compile_void_cast(znode *result, zend_ast *ast) +{ + zend_ast *expr_ast = ast->child[0]; + znode expr_node; + zend_op *opline; + + zend_compile_expr(&expr_node, expr_ast); + + switch (expr_node.op_type) { + case IS_TMP_VAR: + case IS_VAR: + opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); + opline->extended_value = ZEND_FREE_VOID_CAST; + break; + case IS_CONST: + zend_do_free(&expr_node); + break; + } +} + static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; @@ -11547,6 +11567,9 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */ case ZEND_AST_THROW: zend_compile_expr(NULL, ast); break; + case ZEND_AST_CAST_VOID: + zend_compile_void_cast(NULL, ast); + break; default: { znode result; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index a7ee8f9327c54..224a68be749cb 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1092,6 +1092,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define ZEND_FREE_ON_RETURN (1<<0) #define ZEND_FREE_SWITCH (1<<1) +#define ZEND_FREE_VOID_CAST (1<<2) #define ZEND_SEND_BY_VAL 0u #define ZEND_SEND_BY_REF 1u diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 1f117d142c158..9483a83b4e955 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -217,6 +217,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_OBJECT_CAST "'(object)'" %token T_BOOL_CAST "'(bool)'" %token T_UNSET_CAST "'(unset)'" +%token T_VOID_CAST "'(void)'" %token T_OBJECT_OPERATOR "'->'" %token T_NULLSAFE_OBJECT_OPERATOR "'?->'" %token T_DOUBLE_ARROW "'=>'" @@ -534,6 +535,7 @@ statement: { $$ = zend_ast_create(ZEND_AST_TRY, $3, $5, $6); } | T_GOTO T_STRING ';' { $$ = zend_ast_create(ZEND_AST_GOTO, $2); } | T_STRING ':' { $$ = zend_ast_create(ZEND_AST_LABEL, $1); } + | T_VOID_CAST expr ';' { $$ = zend_ast_create(ZEND_AST_CAST_VOID, $2); } ; catch_list: diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 7ae73875926eb..4c883b81c5f7d 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -1657,6 +1657,10 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_UNSET_CAST); } +"("{TABS_AND_SPACES}("void"){TABS_AND_SPACES}")" { + RETURN_TOKEN(T_VOID_CAST); +} + "eval" { RETURN_TOKEN_WITH_IDENT(T_EVAL); } diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c index a046ab50e1498..a1e131032bcfb 100644 --- a/ext/tokenizer/tokenizer_data.c +++ b/ext/tokenizer/tokenizer_data.c @@ -153,6 +153,7 @@ char *get_token_type_name(int token_type) case T_OBJECT_CAST: return "T_OBJECT_CAST"; case T_BOOL_CAST: return "T_BOOL_CAST"; case T_UNSET_CAST: return "T_UNSET_CAST"; + case T_VOID_CAST: return "T_VOID_CAST"; case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR"; case T_NULLSAFE_OBJECT_OPERATOR: return "T_NULLSAFE_OBJECT_OPERATOR"; case T_DOUBLE_ARROW: return "T_DOUBLE_ARROW"; diff --git a/ext/tokenizer/tokenizer_data.stub.php b/ext/tokenizer/tokenizer_data.stub.php index 45f3c89f2de3a..c1e1fd254dfaa 100644 --- a/ext/tokenizer/tokenizer_data.stub.php +++ b/ext/tokenizer/tokenizer_data.stub.php @@ -642,6 +642,11 @@ * @cvalue T_UNSET_CAST */ const T_UNSET_CAST = UNKNOWN; +/** + * @var int + * @cvalue T_VOID_CAST + */ +const T_VOID_CAST = UNKNOWN; /** * @var int * @cvalue T_OBJECT_OPERATOR diff --git a/ext/tokenizer/tokenizer_data_arginfo.h b/ext/tokenizer/tokenizer_data_arginfo.h index 61f6ac1ec3659..9c488d19f1890 100644 --- a/ext/tokenizer/tokenizer_data_arginfo.h +++ b/ext/tokenizer/tokenizer_data_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d917cab61a2b436a16d2227cdb438add45e42d69 */ + * Stub hash: 19d25d22098f46283b517352cbb302db962b50fd */ static void register_tokenizer_data_symbols(int module_number) { @@ -131,6 +131,7 @@ static void register_tokenizer_data_symbols(int module_number) REGISTER_LONG_CONSTANT("T_OBJECT_CAST", T_OBJECT_CAST, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_BOOL_CAST", T_BOOL_CAST, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_UNSET_CAST", T_UNSET_CAST, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_VOID_CAST", T_VOID_CAST, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_OBJECT_OPERATOR", T_OBJECT_OPERATOR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_NULLSAFE_OBJECT_OPERATOR", T_NULLSAFE_OBJECT_OPERATOR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_DOUBLE_ARROW", T_DOUBLE_ARROW, CONST_PERSISTENT); From 0e95233aa2c83a5af5c7e4dd94566d4adf2d9651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 24 Mar 2025 14:47:10 +0100 Subject: [PATCH 159/503] NEWS/UPGRADING --- NEWS | 2 ++ UPGRADING | 3 +++ 2 files changed, 5 insertions(+) diff --git a/NEWS b/NEWS index fcb849ef98a58..a5609377683ed 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ PHP NEWS . Fixed bug GH-18033 (NULL-ptr dereference when using register_tick_function in destructor). (nielsdos) . Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov) + . Added the (void) cast to indicate that not using a value is intentional. + (timwolla) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/UPGRADING b/UPGRADING index 274f45d8f401b..1f58e462e6715 100644 --- a/UPGRADING +++ b/UPGRADING @@ -106,6 +106,9 @@ PHP 8.5 UPGRADE NOTES . Fatal Errors (such as an exceeded maximum execution time) now include a backtrace. RFC: https://wiki.php.net/rfc/error_backtraces_v2 + . Added the (void) to indicate that not using a value is intentional. The + (void) cast does nothing by itself. + RFC: https://wiki.php.net/rfc/marking_return_value_as_important - Curl: . Added support for share handles that are persisted across multiple PHP From efa9e5fdd09a783cbed6a2f2aa9d36110c9bcf43 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Mon, 24 Mar 2025 11:49:26 -0700 Subject: [PATCH 160/503] Add myself as ext/reflection maintainer [skip ci] --- EXTENSIONS | 1 + 1 file changed, 1 insertion(+) diff --git a/EXTENSIONS b/EXTENSIONS index c389b052a8727..dff81142273d2 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -426,6 +426,7 @@ EXTENSION: reflection PRIMARY MAINTAINER: Marcus Börger (2003 - 2009) Johannes Schlüter (2006 - 2014) Nikita Popov (2019 - 2020) + Daniel Scherzer (2025 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- From 556e4d9008a42c8e2ba1ce0be75b0c63099def1c Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 15 Mar 2025 16:59:39 +0000 Subject: [PATCH 161/503] streams: Indicate which argument fails the stream ZPP check --- ext/bz2/tests/004.phpt | 8 +- .../tests/socket_export_stream-4-win.phpt | 4 +- ext/sockets/tests/socket_export_stream-4.phpt | 4 +- .../tests/socket_import_stream-4-win.phpt | 4 +- ext/sockets/tests/socket_import_stream-4.phpt | 4 +- ext/standard/tests/file/007_basic.phpt | 96 +++++++++---------- .../tests/file/fclose_variation1.phpt | 2 +- ext/standard/tests/file/feof_basic.phpt | 2 +- ext/standard/tests/file/fgetc_variation2.phpt | 2 +- ext/standard/tests/file/fgets_variation2.phpt | 4 +- ext/standard/tests/file/flock.phpt | 2 +- ext/standard/tests/file/flock_error.phpt | 2 +- .../tests/file/fseek_ftell_rewind_error1.phpt | 2 +- .../tests/file/fseek_ftell_rewind_error2.phpt | 2 +- .../tests/file/fseek_ftell_rewind_error3.phpt | 2 +- ext/standard/tests/file/fstat.phpt | 2 +- ext/standard/tests/file/ftruncate_error.phpt | 2 +- ext/standard/tests/file/fwrite.phpt | 7 -- ext/standard/tests/file/fwrite_error.phpt | 2 +- .../tests/file/stream_supports_lock.phpt | 2 +- ext/standard/tests/filters/bug54350.phpt | 2 +- ext/standard/tests/streams/bug54623.phpt | 2 +- .../stream_get_meta_data_file_error.phpt | 2 +- .../streams/stream_set_timeout_error.phpt | 2 +- ext/zlib/tests/gzclose_basic.phpt | 4 +- ext/zlib/tests/gzeof_variation1.phpt | 2 +- main/php_streams.h | 20 +++- 27 files changed, 96 insertions(+), 93 deletions(-) diff --git a/ext/bz2/tests/004.phpt b/ext/bz2/tests/004.phpt index e644bfa6ce962..240cef37a17a2 100644 --- a/ext/bz2/tests/004.phpt +++ b/ext/bz2/tests/004.phpt @@ -112,8 +112,8 @@ array(2) { } string(10) "DATA_ERROR" int(-4) -bzread(): supplied resource is not a valid stream resource -bzerror(): supplied resource is not a valid stream resource -bzerrstr(): supplied resource is not a valid stream resource -bzerrno(): supplied resource is not a valid stream resource +bzread(): Argument #1 ($bz) must be an open stream resource +bzerror(): Argument #1 ($bz) must be an open stream resource +bzerrstr(): Argument #1 ($bz) must be an open stream resource +bzerrno(): Argument #1 ($bz) must be an open stream resource Done diff --git a/ext/sockets/tests/socket_export_stream-4-win.phpt b/ext/sockets/tests/socket_export_stream-4-win.phpt index 9eb2b901e1c65..57c7e7a9aeed2 100644 --- a/ext/sockets/tests/socket_export_stream-4-win.phpt +++ b/ext/sockets/tests/socket_export_stream-4-win.phpt @@ -92,7 +92,7 @@ stream_set_blocking 1 close stream -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [%d]: An operation was attempted on something that is not a socket in %s on line %d @@ -103,7 +103,7 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: An operatio close socket -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed diff --git a/ext/sockets/tests/socket_export_stream-4.phpt b/ext/sockets/tests/socket_export_stream-4.phpt index b8b6c954099c7..512a62379e98c 100644 --- a/ext/sockets/tests/socket_export_stream-4.phpt +++ b/ext/sockets/tests/socket_export_stream-4.phpt @@ -94,7 +94,7 @@ stream_set_blocking 1 close stream -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d @@ -105,7 +105,7 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed diff --git a/ext/sockets/tests/socket_import_stream-4-win.phpt b/ext/sockets/tests/socket_import_stream-4-win.phpt index a005347069ed3..ab09f43d92075 100644 --- a/ext/sockets/tests/socket_import_stream-4-win.phpt +++ b/ext/sockets/tests/socket_import_stream-4-win.phpt @@ -87,7 +87,7 @@ stream_set_blocking 1 close stream -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [10038]: %s in %ssocket_import_stream-4-win.php on line %d @@ -98,7 +98,7 @@ Warning: socket_get_option(): Unable to retrieve socket option [10038]: %s in %s close socket -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed diff --git a/ext/sockets/tests/socket_import_stream-4.phpt b/ext/sockets/tests/socket_import_stream-4.phpt index c898d614bcff5..25e425961f613 100644 --- a/ext/sockets/tests/socket_import_stream-4.phpt +++ b/ext/sockets/tests/socket_import_stream-4.phpt @@ -89,7 +89,7 @@ stream_set_blocking 1 close stream -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d @@ -100,7 +100,7 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket -stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): Argument #1 ($stream) must be an open stream resource socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed diff --git a/ext/standard/tests/file/007_basic.phpt b/ext/standard/tests/file/007_basic.phpt index 37047ec32b28b..6a0c918ea39c8 100644 --- a/ext/standard/tests/file/007_basic.phpt +++ b/ext/standard/tests/file/007_basic.phpt @@ -102,8 +102,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'wb' -- resource(%d) of type (stream) @@ -111,8 +111,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'wt' -- resource(%d) of type (stream) @@ -120,8 +120,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'w+' -- resource(%d) of type (stream) @@ -129,8 +129,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'w+b' -- resource(%d) of type (stream) @@ -138,8 +138,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'w+t' -- resource(%d) of type (stream) @@ -147,8 +147,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'r' -- resource(%d) of type (stream) @@ -156,8 +156,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'rb' -- resource(%d) of type (stream) @@ -165,8 +165,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'rt' -- resource(%d) of type (stream) @@ -174,8 +174,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'r+' -- resource(%d) of type (stream) @@ -183,8 +183,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'r+b' -- resource(%d) of type (stream) @@ -192,8 +192,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'r+t' -- resource(%d) of type (stream) @@ -201,8 +201,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'a' -- resource(%d) of type (stream) @@ -210,8 +210,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'ab' -- resource(%d) of type (stream) @@ -219,8 +219,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'at' -- resource(%d) of type (stream) @@ -228,8 +228,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'a+' -- resource(%d) of type (stream) @@ -237,8 +237,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'a+t' -- resource(%d) of type (stream) @@ -246,8 +246,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'a+b' -- resource(%d) of type (stream) @@ -255,8 +255,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource -- Iteration with mode 'x' -- resource(%d) of type (stream) @@ -264,8 +264,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) -- Iteration with mode 'xb' -- @@ -274,8 +274,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) -- Iteration with mode 'xt' -- @@ -284,8 +284,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) -- Iteration with mode 'x+' -- @@ -294,8 +294,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) -- Iteration with mode 'x+b' -- @@ -304,8 +304,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) -- Iteration with mode 'x+t' -- @@ -314,8 +314,8 @@ int(0) bool(false) bool(true) resource(%d) of type (Unknown) -ftell(): supplied resource is not a valid stream resource -feof(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource +feof(): Argument #1 ($stream) must be an open stream resource resource(%d) of type (Unknown) *** Done *** diff --git a/ext/standard/tests/file/fclose_variation1.phpt b/ext/standard/tests/file/fclose_variation1.phpt index 5f6c25860d64f..56a6d4bd4c1c4 100644 --- a/ext/standard/tests/file/fclose_variation1.phpt +++ b/ext/standard/tests/file/fclose_variation1.phpt @@ -15,6 +15,6 @@ try { echo "\nDone.\n"; ?> --EXPECT-- -fread(): supplied resource is not a valid stream resource +fread(): Argument #1 ($stream) must be an open stream resource Done. diff --git a/ext/standard/tests/file/feof_basic.phpt b/ext/standard/tests/file/feof_basic.phpt index a263bf1fbe6c4..943af213e39a2 100644 --- a/ext/standard/tests/file/feof_basic.phpt +++ b/ext/standard/tests/file/feof_basic.phpt @@ -94,5 +94,5 @@ bool(false) *** testing feof after a seek passed the end *** bool(false) *** closing file, testing eof *** -feof(): supplied resource is not a valid stream resource +feof(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/fgetc_variation2.phpt b/ext/standard/tests/file/fgetc_variation2.phpt index 42558998337ed..89161d0881902 100644 --- a/ext/standard/tests/file/fgetc_variation2.phpt +++ b/ext/standard/tests/file/fgetc_variation2.phpt @@ -30,5 +30,5 @@ echo "Done"; --EXPECT-- *** Testing fgetc() : usage variations *** -- Testing fgetc() with closed handle -- -fgetc(): supplied resource is not a valid stream resource +fgetc(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/fgets_variation2.phpt b/ext/standard/tests/file/fgets_variation2.phpt index 28cba347d5ff7..5d262cde295b4 100644 --- a/ext/standard/tests/file/fgets_variation2.phpt +++ b/ext/standard/tests/file/fgets_variation2.phpt @@ -35,6 +35,6 @@ echo "Done"; --EXPECT-- *** Testing fgets() : usage variations *** -- Testing fgets() with closed handle -- -fgets(): supplied resource is not a valid stream resource -fgets(): supplied resource is not a valid stream resource +fgets(): Argument #1 ($stream) must be an open stream resource +fgets(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/flock.phpt b/ext/standard/tests/file/flock.phpt index 346029c7cab27..a3c1804584023 100644 --- a/ext/standard/tests/file/flock.phpt +++ b/ext/standard/tests/file/flock.phpt @@ -46,7 +46,7 @@ $file = __DIR__."/flock.dat"; unlink($file); ?> --EXPECT-- -flock(): supplied resource is not a valid stream resource +flock(): Argument #1 ($stream) must be an open stream resource bool(true) bool(true) bool(true) diff --git a/ext/standard/tests/file/flock_error.phpt b/ext/standard/tests/file/flock_error.phpt index 753aaa6fb34e8..2ca20c3436ab6 100644 --- a/ext/standard/tests/file/flock_error.phpt +++ b/ext/standard/tests/file/flock_error.phpt @@ -70,4 +70,4 @@ flock(): Argument #2 ($operation) must be of type int, string given flock(): Argument #2 ($operation) must be of type int, string given --- Iteration 7 --- flock(): Argument #2 ($operation) must be of type int, string given -flock(): supplied resource is not a valid stream resource +flock(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/standard/tests/file/fseek_ftell_rewind_error1.phpt b/ext/standard/tests/file/fseek_ftell_rewind_error1.phpt index d576403644546..c38f7905399be 100644 --- a/ext/standard/tests/file/fseek_ftell_rewind_error1.phpt +++ b/ext/standard/tests/file/fseek_ftell_rewind_error1.phpt @@ -20,5 +20,5 @@ echo "Done\n"; --EXPECT-- *** Testing fseek() : error conditions *** -- Testing fseek() with closed/unset file handle -- -fseek(): supplied resource is not a valid stream resource +fseek(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/fseek_ftell_rewind_error2.phpt b/ext/standard/tests/file/fseek_ftell_rewind_error2.phpt index 5a947f66587fe..58c3b5330d874 100644 --- a/ext/standard/tests/file/fseek_ftell_rewind_error2.phpt +++ b/ext/standard/tests/file/fseek_ftell_rewind_error2.phpt @@ -20,5 +20,5 @@ echo "Done\n"; --EXPECT-- *** Testing ftell() : error conditions *** -- Testing ftell with closed/unset file handle -- -ftell(): supplied resource is not a valid stream resource +ftell(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/fseek_ftell_rewind_error3.phpt b/ext/standard/tests/file/fseek_ftell_rewind_error3.phpt index f4212ec71b427..ad50244edb3e4 100644 --- a/ext/standard/tests/file/fseek_ftell_rewind_error3.phpt +++ b/ext/standard/tests/file/fseek_ftell_rewind_error3.phpt @@ -20,5 +20,5 @@ echo "Done\n"; --EXPECT-- *** Testing rewind() : error conditions *** -- Testing rewind() with closed/unset file handle -- -rewind(): supplied resource is not a valid stream resource +rewind(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/fstat.phpt b/ext/standard/tests/file/fstat.phpt index b48b06cfe50b9..86d1453f1b728 100644 --- a/ext/standard/tests/file/fstat.phpt +++ b/ext/standard/tests/file/fstat.phpt @@ -72,5 +72,5 @@ array(26) { ["blocks"]=> int(%i) } -fstat(): supplied resource is not a valid stream resource +fstat(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/ftruncate_error.phpt b/ext/standard/tests/file/ftruncate_error.phpt index 752397a461d6f..3397fc25f44ad 100644 --- a/ext/standard/tests/file/ftruncate_error.phpt +++ b/ext/standard/tests/file/ftruncate_error.phpt @@ -35,6 +35,6 @@ unlink( $filename ); Initial file size = 36 -- Testing ftruncate() with closed/unset file handle -- -ftruncate(): supplied resource is not a valid stream resource +ftruncate(): Argument #1 ($stream) must be an open stream resource int(36) Done diff --git a/ext/standard/tests/file/fwrite.phpt b/ext/standard/tests/file/fwrite.phpt index 1494ea7a0f5e8..12bfb6727ec31 100644 --- a/ext/standard/tests/file/fwrite.phpt +++ b/ext/standard/tests/file/fwrite.phpt @@ -17,12 +17,6 @@ var_dump(fwrite($fp, "data", -1)); var_dump(fwrite($fp, "data", 100000)); fclose($fp); -try { - var_dump(fwrite($fp, "data", -1)); -} catch (Throwable $e) { - echo $e::class, ': ', $e->getMessage(), PHP_EOL; -} - var_dump(file_get_contents($filename)); echo "Done\n"; @@ -39,6 +33,5 @@ Notice: fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor in %s bool(false) int(0) int(4) -TypeError: fwrite(): supplied resource is not a valid stream resource string(4) "data" Done diff --git a/ext/standard/tests/file/fwrite_error.phpt b/ext/standard/tests/file/fwrite_error.phpt index d24f7b8084cf0..62ec928a29dfc 100644 --- a/ext/standard/tests/file/fwrite_error.phpt +++ b/ext/standard/tests/file/fwrite_error.phpt @@ -40,5 +40,5 @@ unlink( $filename ); int(0) int(0) -- Testing fwrite() with closed/unset file handle -- -fwrite(): supplied resource is not a valid stream resource +fwrite(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/file/stream_supports_lock.phpt b/ext/standard/tests/file/stream_supports_lock.phpt index 0d2f04b72d9aa..76249e9106ee4 100644 --- a/ext/standard/tests/file/stream_supports_lock.phpt +++ b/ext/standard/tests/file/stream_supports_lock.phpt @@ -44,5 +44,5 @@ bool(false) resource(%d) of type (stream) bool(false) resource(%d) of type (stream-context) -stream_supports_lock(): supplied resource is not a valid stream resource +stream_supports_lock(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/filters/bug54350.phpt b/ext/standard/tests/filters/bug54350.phpt index ae00762890857..da4429ef68d20 100644 --- a/ext/standard/tests/filters/bug54350.phpt +++ b/ext/standard/tests/filters/bug54350.phpt @@ -23,4 +23,4 @@ fwrite($fd, "foo"); ?> --EXPECTF-- Warning: fclose(): %d is not a valid stream resource in %s on line %d -fclose(): supplied resource is not a valid stream resource +fclose(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/standard/tests/streams/bug54623.phpt b/ext/standard/tests/streams/bug54623.phpt index 29d4cbcbeb6c8..d7383fcc8f7ec 100644 --- a/ext/standard/tests/streams/bug54623.phpt +++ b/ext/standard/tests/streams/bug54623.phpt @@ -18,4 +18,4 @@ try { --EXPECTF-- int(%d) int(%d) -fwrite(): supplied resource is not a valid stream resource +fwrite(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_error.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_error.phpt index 61b6182e70a2c..55bdd1860a479 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_error.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_error.phpt @@ -19,5 +19,5 @@ echo "Done"; *** Testing stream_get_meta_data() : error conditions *** -- Testing stream_get_meta_data() function with closed stream resource -- -stream_get_meta_data(): supplied resource is not a valid stream resource +stream_get_meta_data(): Argument #1 ($stream) must be an open stream resource Done diff --git a/ext/standard/tests/streams/stream_set_timeout_error.phpt b/ext/standard/tests/streams/stream_set_timeout_error.phpt index 58894b7d8c23c..5567cb159914b 100644 --- a/ext/standard/tests/streams/stream_set_timeout_error.phpt +++ b/ext/standard/tests/streams/stream_set_timeout_error.phpt @@ -39,7 +39,7 @@ echo "Done"; *** Testing stream_set_timeout() : error conditions *** -- Testing stream_set_timeout() function with a closed socket -- -stream_set_timeout(): supplied resource is not a valid stream resource +stream_set_timeout(): Argument #1 ($stream) must be an open stream resource -- Testing stream_set_timeout() function with a stream that does not support timeouts -- bool(false) diff --git a/ext/zlib/tests/gzclose_basic.phpt b/ext/zlib/tests/gzclose_basic.phpt index 69dc7cfd3a606..c1d6edf4d95e1 100644 --- a/ext/zlib/tests/gzclose_basic.phpt +++ b/ext/zlib/tests/gzclose_basic.phpt @@ -34,6 +34,6 @@ try { ?> --EXPECT-- bool(true) -gzread(): supplied resource is not a valid stream resource +gzread(): Argument #1 ($stream) must be an open stream resource bool(true) -gzread(): supplied resource is not a valid stream resource +gzread(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/zlib/tests/gzeof_variation1.phpt b/ext/zlib/tests/gzeof_variation1.phpt index 40e6899d6e583..fb4191fa7940a 100644 --- a/ext/zlib/tests/gzeof_variation1.phpt +++ b/ext/zlib/tests/gzeof_variation1.phpt @@ -24,4 +24,4 @@ unlink($filename); --EXPECT-- bool(false) bool(false) -gzeof(): supplied resource is not a valid stream resource +gzeof(): Argument #1 ($stream) must be an open stream resource diff --git a/main/php_streams.h b/main/php_streams.h index 80cb96951ee14..f534bc27285f1 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -287,11 +287,21 @@ END_EXTERN_C() BEGIN_EXTERN_C() -static zend_always_inline bool php_stream_zend_parse_arg_into_stream(zval *arg, php_stream **destination_stream_ptr, bool check_null) -{ +static zend_always_inline bool php_stream_zend_parse_arg_into_stream( + zval *arg, + php_stream **destination_stream_ptr, + bool check_null, + uint32_t arg_num +) { if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) { - *destination_stream_ptr = (php_stream*)zend_fetch_resource2(Z_RES_P(arg), "stream", php_file_le_stream(), php_file_le_pstream()); - if (UNEXPECTED(*destination_stream_ptr == NULL)) { + zend_resource *res = Z_RES_P(arg); + /* We do not use zend_fetch_resource2() API, + * as we want to be able to specify the argument number in the type error */ + if (EXPECTED(res->type == php_file_le_stream() || res->type == php_file_le_pstream())) { + *destination_stream_ptr = (php_stream*)res->ptr; + return true; + } else { + zend_argument_type_error(arg_num, "must be an open stream resource"); return false; } } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { @@ -304,7 +314,7 @@ static zend_always_inline bool php_stream_zend_parse_arg_into_stream(zval *arg, #define PHP_Z_PARAM_STREAM_EX(destination_stream_ptr, check_null) \ Z_PARAM_PROLOGUE(0, 0); \ - if (UNEXPECTED(!php_stream_zend_parse_arg_into_stream(_arg, &destination_stream_ptr, check_null))) { \ + if (UNEXPECTED(!php_stream_zend_parse_arg_into_stream(_arg, &destination_stream_ptr, check_null, _i))) { \ _error_code = ZPP_ERROR_FAILURE; \ if (!EG(exception)) { \ _expected_type = check_null ? Z_EXPECTED_RESOURCE_OR_NULL : Z_EXPECTED_RESOURCE; \ From fec4f7f389cf66412c989f4931a17f858ba7d39a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 15 Mar 2025 17:27:35 +0000 Subject: [PATCH 162/503] ext/standard/file: clarify fclose() warning --- ext/spl/tests/bug81691.phpt | 2 +- ext/standard/file.c | 2 +- ext/standard/tests/filters/bug54350.phpt | 2 +- ext/xmlwriter/tests/bug79029.phpt | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/spl/tests/bug81691.phpt b/ext/spl/tests/bug81691.phpt index 597e37a9c8218..5ae5dd6b08fda 100644 --- a/ext/spl/tests/bug81691.phpt +++ b/ext/spl/tests/bug81691.phpt @@ -10,6 +10,6 @@ var_dump($obj->fgets()); ?> --EXPECTF-- -Warning: fclose(): %d is not a valid stream resource in %s on line %d +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d string(6) "flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) { - php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " is not a valid stream resource", stream->res->handle); + php_error_docref(NULL, E_WARNING, "cannot close the provided stream, as it must not be manually closed"); RETURN_FALSE; } diff --git a/ext/standard/tests/filters/bug54350.phpt b/ext/standard/tests/filters/bug54350.phpt index da4429ef68d20..046db0483a9ae 100644 --- a/ext/standard/tests/filters/bug54350.phpt +++ b/ext/standard/tests/filters/bug54350.phpt @@ -22,5 +22,5 @@ fwrite($fd, "foo"); ?> --EXPECTF-- -Warning: fclose(): %d is not a valid stream resource in %s on line %d +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d fclose(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/xmlwriter/tests/bug79029.phpt b/ext/xmlwriter/tests/bug79029.phpt index 7b091e80e84e9..22feb4599e7af 100644 --- a/ext/xmlwriter/tests/bug79029.phpt +++ b/ext/xmlwriter/tests/bug79029.phpt @@ -26,7 +26,7 @@ okey @unlink("bug79029_3.txt"); ?> --EXPECTF-- -Warning: fclose(): %d is not a valid stream resource in %sbug79029.php on line %d +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %sbug79029.php on line %d -Warning: fclose(): %d is not a valid stream resource in %sbug79029.php on line %d +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %sbug79029.php on line %d okey From 1fa11f17ffe62a5bffae3e38c2155013fd21a295 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 04:01:35 +0000 Subject: [PATCH 163/503] ext/dba: Add const modifier for argument to php_dba_make_key() --- ext/dba/dba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 38040f209d98e..dcfab6d70dbbd 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -92,7 +92,7 @@ ZEND_GET_MODULE(dba) #endif /* {{{ php_dba_make_key */ -static zend_string* php_dba_make_key(HashTable *key) +static zend_string* php_dba_make_key(const HashTable *key) { zval *group, *name; zend_string *group_str, *name_str; From e1845365ea58b4c6fa172ba0e3cd289242ed9731 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 04:12:30 +0000 Subject: [PATCH 164/503] ext/enchant: Remove useless char* casts --- ext/enchant/enchant.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c index bcea06a83d7ad..d1d9ee60c440a 100644 --- a/ext/enchant/enchant.c +++ b/ext/enchant/enchant.c @@ -113,9 +113,9 @@ enumerate_providers_fn (const char * const name, array_init(&tmp_array); - add_assoc_string(&tmp_array, "name", (char *)name); - add_assoc_string(&tmp_array, "desc", (char *)desc); - add_assoc_string(&tmp_array, "file", (char *)file); + add_assoc_string(&tmp_array, "name", name); + add_assoc_string(&tmp_array, "desc", desc); + add_assoc_string(&tmp_array, "file", file); add_next_index_zval(zdesc, &tmp_array); } /* }}} */ @@ -129,10 +129,10 @@ describe_dict_fn (const char * const lang, { zval *zdesc = (zval *) ud; array_init(zdesc); - add_assoc_string(zdesc, "lang", (char *)lang); - add_assoc_string(zdesc, "name", (char *)name); - add_assoc_string(zdesc, "desc", (char *)desc); - add_assoc_string(zdesc, "file", (char *)file); + add_assoc_string(zdesc, "lang", lang); + add_assoc_string(zdesc, "name", name); + add_assoc_string(zdesc, "desc", desc); + add_assoc_string(zdesc, "file", file); } /* }}} */ @@ -144,10 +144,10 @@ static void php_enchant_list_dicts_fn( const char * const lang_tag, zval tmp_array; array_init(&tmp_array); - add_assoc_string(&tmp_array, "lang_tag", (char *)lang_tag); - add_assoc_string(&tmp_array, "provider_name", (char *)provider_name); - add_assoc_string(&tmp_array, "provider_desc", (char *)provider_desc); - add_assoc_string(&tmp_array, "provider_file", (char *)provider_file); + add_assoc_string(&tmp_array, "lang_tag", lang_tag); + add_assoc_string(&tmp_array, "provider_name", provider_name); + add_assoc_string(&tmp_array, "provider_desc", provider_desc); + add_assoc_string(&tmp_array, "provider_file", provider_file); add_next_index_zval(zdesc, &tmp_array); } @@ -318,7 +318,7 @@ PHP_FUNCTION(enchant_broker_get_error) msg = enchant_broker_get_error(pbroker->pbroker); if (msg) { - RETURN_STRING((char *)msg); + RETURN_STRING(msg); } RETURN_FALSE; } @@ -346,12 +346,12 @@ PHP_FUNCTION(enchant_broker_set_dict_path) switch (dict_type) { case PHP_ENCHANT_MYSPELL: - enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value); + enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", value); RETURN_TRUE; break; case PHP_ENCHANT_ISPELL: - enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value); + enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", value); RETURN_TRUE; break; @@ -440,7 +440,7 @@ PHP_FUNCTION(enchant_broker_request_dict) RETURN_THROWS(); } - pdict = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag); + pdict = enchant_broker_request_dict(pbroker->pbroker, tag); if (pdict) { pbroker->nb_dict++; From 5ff8d6d0d27359b97e9a65793af9b91f58941ff4 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 22 Feb 2025 22:59:07 +0100 Subject: [PATCH 165/503] Fix GH-17645: FPM with httpd ProxyPass does not decode script path This changes make FPM always decode SCRIPT_FILENAME when Apache ProxyPass or ProxyPassMatch is used. It also introduces a new INI option fastcgi.script_path_encoded that allows using the previous behavior of not decoding the path. The INI is introduced because there is a chance that some users could use encoded file paths in their file system as a workaround for the previous behavior. Close GH-17896 --- NEWS | 4 ++ UPGRADING | 4 ++ php.ini-development | 6 ++ php.ini-production | 6 ++ sapi/fpm/fpm/fpm_main.c | 23 +++++--- .../fcgi-env-pif-apache-pp-sfp-decoding.phpt | 54 ++++++++++++++++++ .../fcgi-env-pif-apache-pp-sfp-encoded.phpt | 55 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 21 +++++-- 8 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-decoding.phpt create mode 100644 sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-encoded.phpt diff --git a/NEWS b/NEWS index a5609377683ed..c2605daa5d86f 100644 --- a/NEWS +++ b/NEWS @@ -62,6 +62,10 @@ PHP NEWS - Fileinfo: . Upgrade to file 5.46. (nielsdos) +- FPM: + . Fixed GH-17645 (FPM with httpd ProxyPass does not decode script path). + (Jakub Zelenka) + - GD: . Fixed bug #68629 (Transparent artifacts when using imagerotate). (pierre, cmb) diff --git a/UPGRADING b/UPGRADING index 1f58e462e6715..6d06234403d66 100644 --- a/UPGRADING +++ b/UPGRADING @@ -152,6 +152,10 @@ PHP 8.5 UPGRADE NOTES . Added a new --ini=diff option to print INI settings changed from the builtin default. +- FPM: + . FPM with httpd ProxyPass decodes the full scirpt path script path. Added + fastcgi.script_path_encoded INI setting to prevent this new behevior. + ======================================== 4. Deprecated Functionality ======================================== diff --git a/php.ini-development b/php.ini-development index 37619fd071c55..162fb3f25c19c 100644 --- a/php.ini-development +++ b/php.ini-development @@ -817,6 +817,12 @@ enable_dl = Off ; https://php.net/fastcgi.impersonate ;fastcgi.impersonate = 1 +; Prevent decoding of SCRIPT_FILENAME when using Apache ProxyPass or +; ProxyPassMatch. This should only be used if script file paths are already +; stored in an encoded format on the file system. +; Default is 0. +;fastcgi.script_path_encoded = 1 + ; Disable logging through FastCGI connection. PHP's default behavior is to enable ; this feature. ;fastcgi.logging = 0 diff --git a/php.ini-production b/php.ini-production index 60069f69b8b90..042d246943d81 100644 --- a/php.ini-production +++ b/php.ini-production @@ -819,6 +819,12 @@ enable_dl = Off ; https://php.net/fastcgi.impersonate ;fastcgi.impersonate = 1 +; Prevent decoding of SCRIPT_FILENAME when using Apache ProxyPass or +; ProxyPassMatch. This should only be used if script file paths are already +; stored in an encoded format on the file system. +; Default is 0. +;fastcgi.script_path_encoded = 1 + ; Disable logging through FastCGI connection. PHP's default behavior is to enable ; this feature. ;fastcgi.logging = 0 diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 12edcedd951df..8af1e51d512fb 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -144,6 +144,7 @@ typedef struct _php_cgi_globals_struct { bool nph; bool fix_pathinfo; bool discard_path; + bool fcgi_script_path_encoded; bool fcgi_logging; bool fcgi_logging_request_started; HashTable user_config_cache; @@ -1066,6 +1067,10 @@ static void init_request_info(void) } } + if (apache_was_here && !CGIG(fcgi_script_path_encoded)) { + php_raw_url_decode(env_script_filename, strlen(env_script_filename)); + } + if (CGIG(fix_pathinfo)) { struct stat st; char *real_path = NULL; @@ -1174,7 +1179,7 @@ static void init_request_info(void) * it is probably also in SCRIPT_NAME and need to be removed */ size_t decoded_path_info_len = 0; - if (strchr(path_info, '%')) { + if (CGIG(fcgi_script_path_encoded) && strchr(path_info, '%')) { decoded_path_info = estrdup(path_info); decoded_path_info_len = php_raw_url_decode(decoded_path_info, strlen(path_info)); } @@ -1421,13 +1426,14 @@ static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_ /* }}} */ PHP_INI_BEGIN() - STD_PHP_INI_BOOLEAN("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_BOOLEAN("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_BOOLEAN("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_BOOLEAN("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_BOOLEAN("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_ENTRY("fpm.config", NULL, PHP_INI_SYSTEM, OnUpdateString, fpm_config, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("fastcgi.script_path_encoded", "0", PHP_INI_SYSTEM, OnUpdateBool, fcgi_script_path_encoded, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_ENTRY("fpm.config", NULL, PHP_INI_SYSTEM, OnUpdateString, fpm_config, php_cgi_globals_struct, php_cgi_globals) PHP_INI_END() /* {{{ php_cgi_globals_ctor */ @@ -1437,6 +1443,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals) php_cgi_globals->nph = 0; php_cgi_globals->fix_pathinfo = 1; php_cgi_globals->discard_path = 0; + php_cgi_globals->fcgi_script_path_encoded = 0; php_cgi_globals->fcgi_logging = 1; php_cgi_globals->fcgi_logging_request_started = false; zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, user_config_cache_entry_dtor, 1); diff --git a/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-decoding.phpt b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-decoding.phpt new file mode 100644 index 0000000000000..d6189107fb84b --- /dev/null +++ b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-decoding.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: FastCGI change for Apache ProxyPass SCRIPT_FILENAME decoding (GH-17645) +--SKIPIF-- + +--FILE-- +createSourceFileAndScriptName('+'); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + uri: $scriptName . '/1%202', + scriptFilename: "proxy:fcgi://" . $tester->getAddr() . str_replace('+', '%2B', $sourceFilePath) . '/1%202', + scriptName: $scriptName . '/1 2' + ) + ->expectBody([$scriptName, $scriptName . '/1 2', $sourceFilePath, '/1 2', $scriptName . '/1 2']); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-encoded.phpt b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-encoded.phpt new file mode 100644 index 0000000000000..3b5ccc86b6926 --- /dev/null +++ b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sfp-encoded.phpt @@ -0,0 +1,55 @@ +--TEST-- +FPM: FastCGI change for Apache ProxyPass SCRIPT_FILENAME decoding - fallback (GH-17645) +--SKIPIF-- + +--FILE-- +createSourceFileAndScriptName('%2B'); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + uri: $scriptName . '/1%202', + scriptFilename: "proxy:fcgi://" . $tester->getAddr() . $sourceFilePath . '/1%202', + scriptName: $scriptName . '/1 2' + ) + ->expectBody([$scriptName, $scriptName . '/1 2', $sourceFilePath, '/1 2', $scriptName . '/1 2']); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 8e67d17430a64..f486309085e6d 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -47,7 +47,7 @@ class Tester self::FILE_EXT_LOG_ERR, self::FILE_EXT_LOG_SLOW, self::FILE_EXT_PID, - 'src.php', + '*src.php', 'ini', 'skip.ini', '*.sock', @@ -107,6 +107,11 @@ class Tester */ private string $fileName; + /** + * @var string + */ + private ?string $sourceFile = null; + /** * @var resource */ @@ -1483,21 +1488,27 @@ class Tester /** * Create a source code file. * + * @param string $nameSuffix * @return string */ - public function makeSourceFile(): string + public function makeSourceFile(string $nameSuffix = ''): string { - return $this->makeFile('src.php', $this->code, overwrite: false); + if (is_null($this->sourceFile)) { + $this->sourceFile = $this->makeFile($nameSuffix . 'src.php', $this->code, overwrite: false); + } + + return $this->sourceFile; } /** * Create a source file and script name. * + * @param string $nameSuffix * @return string[] */ - public function createSourceFileAndScriptName(): array + public function createSourceFileAndScriptName(string $nameSuffix = ''): array { - $sourceFile = $this->makeFile('src.php', $this->code, overwrite: false); + $sourceFile = $this->makeSourceFile($nameSuffix); return [$sourceFile, '/' . basename($sourceFile)]; } From c45d608569c8ba886944c0a6ae3001015e7ef27b Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Tue, 25 Mar 2025 11:20:12 -0700 Subject: [PATCH 166/503] Add myself as ext/reflection codeowner [skip ci] --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ba67073c6afb3..8f8273e0ef5ac 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -45,6 +45,7 @@ /ext/pdo_sqlite @SakiTakamachi /ext/pgsql @devnexen /ext/random @TimWolla @zeriyoshi +/ext/reflection @DanielEScherzer /ext/session @Girgias /ext/simplexml @nielsdos /ext/soap @nielsdos From 9d0c492d304b341bce19f4b552c64eb536e19944 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Tue, 25 Mar 2025 16:38:46 -0300 Subject: [PATCH 167/503] Bump for 8.4.7-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 0f8bd8f3d656a..f629af3a622a1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.4.6 +?? ??? ????, PHP 8.4.7 + + +27 Mar 2025, PHP 8.4.6RC1 - BCMath: . Fixed pointer subtraction for scale. (SakiTakamachi) diff --git a/Zend/zend.h b/Zend/zend.h index c787b54940d92..2e5fb5d0ef091 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.4.6-dev" +#define ZEND_VERSION "4.4.7-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 63a30a9def502..0e12d55b00963 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.4.6-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.4.7-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index e46868a3abd88..414e0e8f5a68a 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 4 -#define PHP_RELEASE_VERSION 6 +#define PHP_RELEASE_VERSION 7 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.4.6-dev" -#define PHP_VERSION_ID 80406 +#define PHP_VERSION "8.4.7-dev" +#define PHP_VERSION_ID 80407 From 7acce8a724aaadc00f9b61882aef19cbd517b576 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 25 Mar 2025 20:49:27 +0100 Subject: [PATCH 168/503] Avoid allocating temporaries on the call frame for property hook trampolines (#16287) As pointed out in https://github.com/php/php-src/pull/16252#issuecomment-2396745309 --- Zend/zend_object_handlers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index f2c2886eeb2be..3b3ecfc590d2a 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1731,6 +1731,9 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( func = (zend_function *)(uintptr_t)ecalloc(1, sizeof(zend_internal_function)); } func->type = ZEND_INTERNAL_FUNCTION; + /* This trampoline does not use the call_trampoline_op, so it won't reuse the call frame, + * which means we don't even need to reserve a temporary for observers. */ + func->common.T = 0; func->common.arg_flags[0] = 0; func->common.arg_flags[1] = 0; func->common.arg_flags[2] = 0; From b57f425cfe20a11003253427424cc0517483550b Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 25 Mar 2025 22:09:16 +0100 Subject: [PATCH 169/503] PHP 8.3 is now for PHP 8.3.21-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index caad04f9d0895..22f3d75974629 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.20 +?? ??? ????, PHP 8.3.21 + + +10 Apr 2025, PHP 8.3.20 - Core: . Fixed bug GH-17961 (use-after-free during dl()'ed module class destruction). diff --git a/Zend/zend.h b/Zend/zend.h index 927088ea18706..139e6a70e15dd 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.20-dev" +#define ZEND_VERSION "4.3.21-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index a94d4958492fd..d721458a73eb2 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.20-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.21-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 3dee6de933251..eb91f434188c6 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 -#define PHP_RELEASE_VERSION 20 +#define PHP_RELEASE_VERSION 21 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.20-dev" -#define PHP_VERSION_ID 80320 +#define PHP_VERSION "8.3.21-dev" +#define PHP_VERSION_ID 80321 From 1ce79eb21969af630470a3bd5786dc4d22ead1e7 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Wed, 26 Mar 2025 07:48:02 +0900 Subject: [PATCH 170/503] ext/bcmath: In the arm processor environment, NEON is used to use SIMD. (#18130) --- ext/bcmath/libbcmath/src/convert.c | 22 +++++------ ext/bcmath/libbcmath/src/simd.h | 59 ++++++++++++++++++++++++++++++ ext/bcmath/libbcmath/src/str2num.c | 40 ++++++++++---------- 3 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 ext/bcmath/libbcmath/src/simd.h diff --git a/ext/bcmath/libbcmath/src/convert.c b/ext/bcmath/libbcmath/src/convert.c index bf3d9a9a415bf..5438b4c1c44e5 100644 --- a/ext/bcmath/libbcmath/src/convert.c +++ b/ext/bcmath/libbcmath/src/convert.c @@ -17,24 +17,22 @@ #include "bcmath.h" #include "convert.h" #include "private.h" -#ifdef __SSE2__ -# include -#endif +#include "simd.h" char *bc_copy_and_toggle_bcd(char *restrict dest, const char *source, const char *source_end) { const size_t bulk_shift = SWAR_REPEAT('0'); -#ifdef __SSE2__ - /* SIMD SSE2 bulk shift + copy */ - __m128i shift_vector = _mm_set1_epi8('0'); - while (source + sizeof(__m128i) <= source_end) { - __m128i bytes = _mm_loadu_si128((const __m128i *) source); - bytes = _mm_xor_si128(bytes, shift_vector); - _mm_storeu_si128((__m128i *) dest, bytes); +#ifdef HAVE_BC_SIMD_128 + /* SIMD SSE2 or NEON bulk shift + copy */ + bc_simd_128_t shift_vector = bc_simd_set_8x16('0'); + while (source + sizeof(bc_simd_128_t) <= source_end) { + bc_simd_128_t bytes = bc_simd_load_8x16((const bc_simd_128_t *) source); + bytes = bc_simd_xor_8x16(bytes, shift_vector); + bc_simd_store_8x16((bc_simd_128_t *) dest, bytes); - source += sizeof(__m128i); - dest += sizeof(__m128i); + source += sizeof(bc_simd_128_t); + dest += sizeof(bc_simd_128_t); } #endif diff --git a/ext/bcmath/libbcmath/src/simd.h b/ext/bcmath/libbcmath/src/simd.h new file mode 100644 index 0000000000000..af38f8349618c --- /dev/null +++ b/ext/bcmath/libbcmath/src/simd.h @@ -0,0 +1,59 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Saki Takamachi | + +----------------------------------------------------------------------+ +*/ + + +#ifndef _BCMATH_SIMD_H_ +#define _BCMATH_SIMD_H_ + +#ifdef __SSE2__ +# include + typedef __m128i bc_simd_128_t; +# define HAVE_BC_SIMD_128 +# define bc_simd_set_8x16(x) _mm_set1_epi8(x) +# define bc_simd_load_8x16(ptr) _mm_loadu_si128((const __m128i *) (ptr)) +# define bc_simd_xor_8x16(a, b) _mm_xor_si128(a, b) +# define bc_simd_store_8x16(ptr, val) _mm_storeu_si128((__m128i *) (ptr), val) +# define bc_simd_add_8x16(a, b) _mm_add_epi8(a, b) +# define bc_simd_cmpeq_8x16(a, b) _mm_cmpeq_epi8(a, b) +# define bc_simd_cmplt_8x16(a, b) _mm_cmplt_epi8(a, b) +# define bc_simd_movemask_8x16(a) _mm_movemask_epi8(a) + +#elif defined(__aarch64__) || defined(_M_ARM64) +# include + typedef int8x16_t bc_simd_128_t; +# define HAVE_BC_SIMD_128 +# define bc_simd_set_8x16(x) vdupq_n_s8(x) +# define bc_simd_load_8x16(ptr) vld1q_s8((const int8_t *) (ptr)) +# define bc_simd_xor_8x16(a, b) veorq_s8(a, b) +# define bc_simd_store_8x16(ptr, val) vst1q_s8((int8_t *) (ptr), val) +# define bc_simd_add_8x16(a, b) vaddq_s8(a, b) +# define bc_simd_cmpeq_8x16(a, b) (vreinterpretq_s8_u8(vceqq_s8(a, b))) +# define bc_simd_cmplt_8x16(a, b) (vreinterpretq_s8_u8(vcltq_s8(a, b))) + static inline int bc_simd_movemask_8x16(int8x16_t vec) + { + /** + * based on code from + * https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon + */ + uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(vreinterpretq_u8_s8(vec), 7)); + uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); + uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8); + } +#endif + +#endif diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c index bd9a44a240503..945de0cf60003 100644 --- a/ext/bcmath/libbcmath/src/str2num.c +++ b/ext/bcmath/libbcmath/src/str2num.c @@ -32,30 +32,28 @@ #include "bcmath.h" #include "convert.h" #include "private.h" +#include "simd.h" #include #include -#ifdef __SSE2__ -# include -#endif /* Convert strings to bc numbers. Base 10 only.*/ -static const char *bc_count_digits(const char *str, const char *end) +static inline const char *bc_count_digits(const char *str, const char *end) { /* Process in bulk */ -#ifdef __SSE2__ - const __m128i offset = _mm_set1_epi8((signed char) (SCHAR_MIN - '0')); +#ifdef HAVE_BC_SIMD_128 + const bc_simd_128_t offset = bc_simd_set_8x16((signed char) (SCHAR_MIN - '0')); /* we use the less than comparator, so add 1 */ - const __m128i threshold = _mm_set1_epi8(SCHAR_MIN + ('9' + 1 - '0')); + const bc_simd_128_t threshold = bc_simd_set_8x16(SCHAR_MIN + ('9' + 1 - '0')); - while (str + sizeof(__m128i) <= end) { - __m128i bytes = _mm_loadu_si128((const __m128i *) str); + while (str + sizeof(bc_simd_128_t) <= end) { + bc_simd_128_t bytes = bc_simd_load_8x16((const bc_simd_128_t *) str); /* Wrapping-add the offset to the bytes, such that all bytes below '0' are positive and others are negative. * More specifically, '0' will be -128 and '9' will be -119. */ - bytes = _mm_add_epi8(bytes, offset); + bytes = bc_simd_add_8x16(bytes, offset); /* Now mark all bytes that are <= '9', i.e. <= -119, i.e. < -118, i.e. the threshold. */ - bytes = _mm_cmplt_epi8(bytes, threshold); + bytes = bc_simd_cmplt_8x16(bytes, threshold); - int mask = _mm_movemask_epi8(bytes); + int mask = bc_simd_movemask_8x16(bytes); if (mask != 0xffff) { /* At least one of the bytes is not within range. Move to the first offending byte. */ #ifdef PHP_HAVE_BUILTIN_CTZL @@ -65,7 +63,7 @@ static const char *bc_count_digits(const char *str, const char *end) #endif } - str += sizeof(__m128i); + str += sizeof(bc_simd_128_t); } #endif @@ -79,19 +77,19 @@ static const char *bc_count_digits(const char *str, const char *end) static inline const char *bc_skip_zero_reverse(const char *scanner, const char *stop) { /* Check in bulk */ -#ifdef __SSE2__ - const __m128i c_zero_repeat = _mm_set1_epi8('0'); - while (scanner - sizeof(__m128i) >= stop) { - scanner -= sizeof(__m128i); - __m128i bytes = _mm_loadu_si128((const __m128i *) scanner); +#ifdef HAVE_BC_SIMD_128 + const bc_simd_128_t c_zero_repeat = bc_simd_set_8x16('0'); + while (scanner - sizeof(bc_simd_128_t) >= stop) { + scanner -= sizeof(bc_simd_128_t); + bc_simd_128_t bytes = bc_simd_load_8x16((const bc_simd_128_t *) scanner); /* Checks if all numeric strings are equal to '0'. */ - bytes = _mm_cmpeq_epi8(bytes, c_zero_repeat); + bytes = bc_simd_cmpeq_8x16(bytes, c_zero_repeat); - int mask = _mm_movemask_epi8(bytes); + int mask = bc_simd_movemask_8x16(bytes); /* The probability of having 16 trailing 0s in a row is very low, so we use EXPECTED. */ if (EXPECTED(mask != 0xffff)) { /* Move the pointer back and check each character in loop. */ - scanner += sizeof(__m128i); + scanner += sizeof(bc_simd_128_t); break; } } From 9c6fe6b0ffbd21bf8580ce00114f83b996577ffe Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 26 Mar 2025 12:47:57 +0000 Subject: [PATCH 171/503] Fix GH-18148: pg_copy_from() wrong \n offset check. Close GH-18149 --- NEWS | 4 ++++ ext/pgsql/pgsql.c | 6 ++++-- ext/pgsql/tests/gh18148.phpt | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 ext/pgsql/tests/gh18148.phpt diff --git a/NEWS b/NEWS index f629af3a622a1..d747ba1b07b93 100644 --- a/NEWS +++ b/NEWS @@ -75,6 +75,10 @@ PHP NEWS - PDO: . Fix memory leak when destroying PDORow. (nielsdos) +- PGSQL: + . Fixed bug GH-18148 (pg_copy_from() regression with explicit \n terminator + due to wrong offset check). (David Carlier) + - Standard: . Fix memory leaks in array_any() / array_all(). (nielsdos) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 4b03bfc3c9df4..c0d4a5117aefc 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -3451,11 +3451,13 @@ PHP_FUNCTION(pg_copy_from) if (UNEXPECTED(!tmp)) { return; } - zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 1, false); + // we give allocation room for a potential command line `\n` terminator addition + zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 2, false); memcpy(ZSTR_VAL(zquery), ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1); ZSTR_LEN(zquery) = ZSTR_LEN(tmp); - if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] != '\n') { + if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp) - 1] != '\n') { ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] = '\n'; + ZSTR_VAL(zquery)[ZSTR_LEN(tmp) + 1] = '\0'; ZSTR_LEN(zquery) ++; } if (PQputCopyData(pgsql, ZSTR_VAL(zquery), ZSTR_LEN(zquery)) != 1) { diff --git a/ext/pgsql/tests/gh18148.phpt b/ext/pgsql/tests/gh18148.phpt new file mode 100644 index 0000000000000..6cc2a2542086f --- /dev/null +++ b/ext/pgsql/tests/gh18148.phpt @@ -0,0 +1,24 @@ +--TEST-- +Fix GH-18148 pg_copy_from() command position offset when giving explicit \n terminator +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) From 6c81f708c5c6c5243c47589b6a1569f710415955 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Thu, 19 Sep 2024 01:43:01 -0700 Subject: [PATCH 172/503] ReflectionClass: test enum output In preparation for improving it, GH-15766 --- .../ReflectionEnum_toString_backed_int.phpt | 141 ++++++++++++++++++ ...ReflectionEnum_toString_backed_string.phpt | 141 ++++++++++++++++++ .../ReflectionEnum_toString_unbacked.phpt | 117 +++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt create mode 100644 ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt create mode 100644 ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt diff --git a/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt b/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt new file mode 100644 index 0000000000000..3a737390e04a2 --- /dev/null +++ b/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt @@ -0,0 +1,141 @@ +--TEST-- +ReflectionEnum::__toString() (larger case, int-backed) +--FILE-- +name . " = " . $this->value; + } +} + +$r = new ReflectionClass( MyBool::class ); +echo $r; +echo "\n"; +$r = new ReflectionEnum( MyBool::class ); +echo $r; + +var_export( MyBool::cases() ); + +?> +--EXPECTF-- +Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { + @@ %sReflectionEnum_toString_backed_int.php 7-16 + + - Constants [3] { + Constant [ public MyBool MyFalse ] { Object } + Constant [ public MyBool MyTrue ] { Object } + Constant [ public MyBool OtherTrue ] { Object } + } + + - Static properties [0] { + } + + - Static methods [3] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + + Method [ static public method from ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ static ] + } + + Method [ static public method tryFrom ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ ?static ] + } + } + + - Properties [2] { + Property [ public protected(set) readonly string $name ] + Property [ public protected(set) readonly int $value ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_backed_int.php 13 - 15 + + - Parameters [0] { + } + - Return [ string ] + } + } +} + +Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { + @@ %sReflectionEnum_toString_backed_int.php 7-16 + + - Constants [3] { + Constant [ public MyBool MyFalse ] { Object } + Constant [ public MyBool MyTrue ] { Object } + Constant [ public MyBool OtherTrue ] { Object } + } + + - Static properties [0] { + } + + - Static methods [3] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + + Method [ static public method from ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ static ] + } + + Method [ static public method tryFrom ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ ?static ] + } + } + + - Properties [2] { + Property [ public protected(set) readonly string $name ] + Property [ public protected(set) readonly int $value ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_backed_int.php 13 - 15 + + - Parameters [0] { + } + - Return [ string ] + } + } +} +array ( + 0 => + \MyBool::MyFalse, + 1 => + \MyBool::MyTrue, +) diff --git a/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt b/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt new file mode 100644 index 0000000000000..c9bc8f2339a03 --- /dev/null +++ b/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt @@ -0,0 +1,141 @@ +--TEST-- +ReflectionEnum::__toString() (larger case, string-backed) +--FILE-- +name . " = " . $this->value; + } +} + +$r = new ReflectionClass( MyBool::class ); +echo $r; +echo "\n"; +$r = new ReflectionEnum( MyBool::class ); +echo $r; + +var_export( MyBool::cases() ); + +?> +--EXPECTF-- +Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { + @@ %sReflectionEnum_toString_backed_string.php 7-16 + + - Constants [3] { + Constant [ public MyBool MyFalse ] { Object } + Constant [ public MyBool MyTrue ] { Object } + Constant [ public MyBool OtherTrue ] { Object } + } + + - Static properties [0] { + } + + - Static methods [3] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + + Method [ static public method from ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ static ] + } + + Method [ static public method tryFrom ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ ?static ] + } + } + + - Properties [2] { + Property [ public protected(set) readonly string $name ] + Property [ public protected(set) readonly string $value ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_backed_string.php 13 - 15 + + - Parameters [0] { + } + - Return [ string ] + } + } +} + +Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { + @@ %sReflectionEnum_toString_backed_string.php 7-16 + + - Constants [3] { + Constant [ public MyBool MyFalse ] { Object } + Constant [ public MyBool MyTrue ] { Object } + Constant [ public MyBool OtherTrue ] { Object } + } + + - Static properties [0] { + } + + - Static methods [3] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + + Method [ static public method from ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ static ] + } + + Method [ static public method tryFrom ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ ?static ] + } + } + + - Properties [2] { + Property [ public protected(set) readonly string $name ] + Property [ public protected(set) readonly string $value ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_backed_string.php 13 - 15 + + - Parameters [0] { + } + - Return [ string ] + } + } +} +array ( + 0 => + \MyBool::MyFalse, + 1 => + \MyBool::MyTrue, +) diff --git a/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt b/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt new file mode 100644 index 0000000000000..32485cadf8b46 --- /dev/null +++ b/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt @@ -0,0 +1,117 @@ +--TEST-- +ReflectionEnum::__toString() (larger case, unbacked) +--FILE-- +name; + } +} + +$r = new ReflectionClass( Suit::class ); +echo $r; +echo "\n"; +$r = new ReflectionEnum( Suit::class ); +echo $r; + +var_export( Suit::cases() ); + +?> +--EXPECTF-- +Class [ final class Suit implements MyStringable, UnitEnum ] { + @@ %sReflectionEnum_toString_unbacked.php 7-18 + + - Constants [5] { + Constant [ public Suit Hearts ] { Object } + Constant [ public Suit Diamonds ] { Object } + Constant [ public Suit Clubs ] { Object } + Constant [ public Suit Spades ] { Object } + Constant [ public Suit OtherHearts ] { Object } + } + + - Static properties [0] { + } + + - Static methods [1] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + } + + - Properties [1] { + Property [ public protected(set) readonly string $name ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_unbacked.php 15 - 17 + + - Parameters [0] { + } + - Return [ string ] + } + } +} + +Class [ final class Suit implements MyStringable, UnitEnum ] { + @@ %sReflectionEnum_toString_unbacked.php 7-18 + + - Constants [5] { + Constant [ public Suit Hearts ] { Object } + Constant [ public Suit Diamonds ] { Object } + Constant [ public Suit Clubs ] { Object } + Constant [ public Suit Spades ] { Object } + Constant [ public Suit OtherHearts ] { Object } + } + + - Static properties [0] { + } + + - Static methods [1] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + } + + - Properties [1] { + Property [ public protected(set) readonly string $name ] + } + + - Methods [1] { + Method [ public method toString ] { + @@ %sReflectionEnum_toString_unbacked.php 15 - 17 + + - Parameters [0] { + } + - Return [ string ] + } + } +} +array ( + 0 => + \Suit::Hearts, + 1 => + \Suit::Diamonds, + 2 => + \Suit::Clubs, + 3 => + \Suit::Spades, +) From 4233394e8f11ecb7899d3cd22d77858940ae00f6 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Wed, 26 Mar 2025 13:00:03 -0700 Subject: [PATCH 173/503] ReflectionClass: show enums differently from classes While internally enums are mostly the same as classes, their output in `ReflectionClass::__toString()` should show the enum as the developer wrote it, rather than as the engine stored it. Accordingly - Say that the enum is an enum, not a final class - Include the backing type, if any, in the declaration line - List enum cases separately from constants, and show the underlying values, if any GH-15766 --- ext/reflection/php_reflection.c | 73 +++++++++++++++++-- .../tests/ReflectionEnumUnitCase_getEnum.phpt | 9 ++- .../tests/ReflectionEnum_toString.phpt | 9 ++- .../ReflectionEnum_toString_backed_int.phpt | 22 ++++-- ...ReflectionEnum_toString_backed_string.phpt | 22 ++++-- .../ReflectionEnum_toString_unbacked.phpt | 30 +++++--- 6 files changed, 126 insertions(+), 39 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index bc8ffbdd8bd8e..7aedca43d02ce 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -306,6 +306,7 @@ static void _const_string(smart_str *str, const char *name, zval *value, const c static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, const char* indent); static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, const char* indent); static void _class_const_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char* indent); +static void _enum_case_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char* indent); static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const char *indent); static void _extension_string(smart_str *str, const zend_module_entry *module, const char *indent); static void _zend_extension_string(smart_str *str, const zend_extension *extension, const char *indent); @@ -330,6 +331,8 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const kind = "Interface"; } else if (ce->ce_flags & ZEND_ACC_TRAIT) { kind = "Trait"; + } else if (ce->ce_flags & ZEND_ACC_ENUM) { + kind = "Enum"; } smart_str_append_printf(str, "%s%s [ ", indent, kind); } @@ -345,6 +348,8 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const smart_str_append_printf(str, "interface "); } else if (ce->ce_flags & ZEND_ACC_TRAIT) { smart_str_append_printf(str, "trait "); + } else if (ce->ce_flags & ZEND_ACC_ENUM) { + smart_str_append_printf(str, "enum "); } else { if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { smart_str_append_printf(str, "abstract "); @@ -362,6 +367,12 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name)); } + // Show backing type of enums + if ((ce->ce_flags & ZEND_ACC_ENUM) && (ce->enum_backing_type != IS_UNDEF)) { + smart_str_append_printf(str, + ce->enum_backing_type == IS_STRING ? ": string" : ": int" + ); + } if (ce->num_interfaces) { uint32_t i; @@ -384,23 +395,49 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const } /* Constants */ - smart_str_append_printf(str, "\n"); - count = zend_hash_num_elements(&ce->constants_table); - smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count); - if (count > 0) { + uint32_t total_count = zend_hash_num_elements(&ce->constants_table); + uint32_t constant_count = 0; + uint32_t enum_case_count = 0; + smart_str constant_str = {0}; + smart_str enum_case_str = {0}; + /* So that we don't need to loop through all of the constants multiple + * times (count the constants vs. enum cases, print the constants, print + * the enum cases) use some temporary helper smart strings. */ + if (total_count > 0) { zend_string *key; zend_class_constant *c; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, c) { - _class_const_string(str, key, c, ZSTR_VAL(sub_indent)); + if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) { + _enum_case_string(&enum_case_str, key, c, ZSTR_VAL(sub_indent)); + enum_case_count++; + } else { + _class_const_string(&constant_str, key, c, ZSTR_VAL(sub_indent)); + constant_count++; + } if (UNEXPECTED(EG(exception))) { zend_string_release(sub_indent); + smart_str_free(&enum_case_str); + smart_str_free(&constant_str); return; } } ZEND_HASH_FOREACH_END(); } + // Enum cases go first, but the heading is only shown if there are any + if (enum_case_count) { + smart_str_appendc(str, '\n'); + smart_str_append_printf(str, "%s - Enum cases [%d] {\n", indent, enum_case_count); + smart_str_append_smart_str(str, &enum_case_str); + smart_str_append_printf(str, "%s }\n", indent); + } + smart_str_appendc(str, '\n'); + smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, constant_count); + smart_str_append_smart_str(str, &constant_str); smart_str_append_printf(str, "%s }\n", indent); + smart_str_free(&enum_case_str); + smart_str_free(&constant_str); + /* Static properties */ /* counting static properties */ count = zend_hash_num_elements(&ce->properties_info); @@ -626,6 +663,32 @@ static void _class_const_string(smart_str *str, const zend_string *name, zend_cl } /* }}} */ +static void _enum_case_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char *indent) +{ + if (Z_TYPE(c->value) == IS_CONSTANT_AST && zend_update_class_constant(c, name, c->ce) == FAILURE) { + return; + } + + if (c->doc_comment) { + smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(c->doc_comment)); + } + smart_str_append_printf(str, "%sCase %s", indent, ZSTR_VAL(name)); + if (c->ce->enum_backing_type == IS_UNDEF) { + // No value + smart_str_appendc(str, '\n'); + } else { + /* Has a value, which is the enum instance, get the value from that. + * We know it must be either a string or integer so no need + * for the IS_ARRAY or IS_OBJECT handling that _class_const_string() + * requires. */ + zval *enum_val = zend_enum_fetch_case_value(Z_OBJ(c->value)); + zend_string *tmp_value_str; + zend_string *value_str = zval_get_tmp_string(enum_val, &tmp_value_str); + smart_str_append_printf(str, " = %s\n", ZSTR_VAL(value_str)); + zend_tmp_string_release(tmp_value_str); + } +} + static zend_op *get_recv_op(const zend_op_array *op_array, uint32_t offset) { zend_op *op = op_array->opcodes; diff --git a/ext/reflection/tests/ReflectionEnumUnitCase_getEnum.phpt b/ext/reflection/tests/ReflectionEnumUnitCase_getEnum.phpt index f9c05d2f6e596..c3d925913a481 100644 --- a/ext/reflection/tests/ReflectionEnumUnitCase_getEnum.phpt +++ b/ext/reflection/tests/ReflectionEnumUnitCase_getEnum.phpt @@ -11,11 +11,14 @@ echo (new ReflectionEnumUnitCase(Foo::class, 'Bar'))->getEnum(); ?> --EXPECTF-- -Class [ final class Foo implements UnitEnum ] { +Enum [ enum Foo implements UnitEnum ] { @@ %sReflectionEnumUnitCase_getEnum.php 3-5 - - Constants [1] { - Constant [ public Foo Bar ] { Object } + - Enum cases [1] { + Case Bar + } + + - Constants [0] { } - Static properties [0] { diff --git a/ext/reflection/tests/ReflectionEnum_toString.phpt b/ext/reflection/tests/ReflectionEnum_toString.phpt index 91ef587a9a3a4..5407afba682ae 100644 --- a/ext/reflection/tests/ReflectionEnum_toString.phpt +++ b/ext/reflection/tests/ReflectionEnum_toString.phpt @@ -11,11 +11,14 @@ echo new ReflectionEnum(Foo::class); ?> --EXPECTF-- -Class [ final class Foo implements UnitEnum ] { +Enum [ enum Foo implements UnitEnum ] { @@ %sReflectionEnum_toString.php 3-5 - - Constants [1] { - Constant [ public Foo Bar ] { Object } + - Enum cases [1] { + Case Bar + } + + - Constants [0] { } - Static properties [0] { diff --git a/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt b/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt index 3a737390e04a2..24ffbf918eaaa 100644 --- a/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt +++ b/ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt @@ -28,12 +28,15 @@ var_export( MyBool::cases() ); ?> --EXPECTF-- -Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { +Enum [ enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] { @@ %sReflectionEnum_toString_backed_int.php 7-16 - - Constants [3] { - Constant [ public MyBool MyFalse ] { Object } - Constant [ public MyBool MyTrue ] { Object } + - Enum cases [2] { + Case MyFalse = 0 + Case MyTrue = 1 + } + + - Constants [1] { Constant [ public MyBool OtherTrue ] { Object } } @@ -81,12 +84,15 @@ Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum } } -Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { +Enum [ enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] { @@ %sReflectionEnum_toString_backed_int.php 7-16 - - Constants [3] { - Constant [ public MyBool MyFalse ] { Object } - Constant [ public MyBool MyTrue ] { Object } + - Enum cases [2] { + Case MyFalse = 0 + Case MyTrue = 1 + } + + - Constants [1] { Constant [ public MyBool OtherTrue ] { Object } } diff --git a/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt b/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt index c9bc8f2339a03..4c38d2b624b39 100644 --- a/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt +++ b/ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt @@ -28,12 +28,15 @@ var_export( MyBool::cases() ); ?> --EXPECTF-- -Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { +Enum [ enum MyBool: string implements MyStringable, UnitEnum, BackedEnum ] { @@ %sReflectionEnum_toString_backed_string.php 7-16 - - Constants [3] { - Constant [ public MyBool MyFalse ] { Object } - Constant [ public MyBool MyTrue ] { Object } + - Enum cases [2] { + Case MyFalse = ~FALSE~ + Case MyTrue = ~TRUE~ + } + + - Constants [1] { Constant [ public MyBool OtherTrue ] { Object } } @@ -81,12 +84,15 @@ Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum } } -Class [ final class MyBool implements MyStringable, UnitEnum, BackedEnum ] { +Enum [ enum MyBool: string implements MyStringable, UnitEnum, BackedEnum ] { @@ %sReflectionEnum_toString_backed_string.php 7-16 - - Constants [3] { - Constant [ public MyBool MyFalse ] { Object } - Constant [ public MyBool MyTrue ] { Object } + - Enum cases [2] { + Case MyFalse = ~FALSE~ + Case MyTrue = ~TRUE~ + } + + - Constants [1] { Constant [ public MyBool OtherTrue ] { Object } } diff --git a/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt b/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt index 32485cadf8b46..ec3d73ab70452 100644 --- a/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt +++ b/ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt @@ -30,14 +30,17 @@ var_export( Suit::cases() ); ?> --EXPECTF-- -Class [ final class Suit implements MyStringable, UnitEnum ] { +Enum [ enum Suit implements MyStringable, UnitEnum ] { @@ %sReflectionEnum_toString_unbacked.php 7-18 - - Constants [5] { - Constant [ public Suit Hearts ] { Object } - Constant [ public Suit Diamonds ] { Object } - Constant [ public Suit Clubs ] { Object } - Constant [ public Suit Spades ] { Object } + - Enum cases [4] { + Case Hearts + Case Diamonds + Case Clubs + Case Spades + } + + - Constants [1] { Constant [ public Suit OtherHearts ] { Object } } @@ -68,14 +71,17 @@ Class [ final class Suit implements MyStringable, UnitEnum ] { } } -Class [ final class Suit implements MyStringable, UnitEnum ] { +Enum [ enum Suit implements MyStringable, UnitEnum ] { @@ %sReflectionEnum_toString_unbacked.php 7-18 - - Constants [5] { - Constant [ public Suit Hearts ] { Object } - Constant [ public Suit Diamonds ] { Object } - Constant [ public Suit Clubs ] { Object } - Constant [ public Suit Spades ] { Object } + - Enum cases [4] { + Case Hearts + Case Diamonds + Case Clubs + Case Spades + } + + - Constants [1] { Constant [ public Suit OtherHearts ] { Object } } From 36ae82b73e2ca97fdda2a78d114a578ce01c81f5 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Wed, 26 Mar 2025 14:17:25 -0700 Subject: [PATCH 174/503] NEWS/UPGRADING for GH-15956 --- NEWS | 2 ++ UPGRADING | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/NEWS b/NEWS index c2605daa5d86f..d1165539400e7 100644 --- a/NEWS +++ b/NEWS @@ -125,6 +125,8 @@ PHP NEWS (DanielEScherzer) . Fixed bug GH-12856 (ReflectionClass::getStaticPropertyValue() returns UNDEF zval for uninitialized typed properties). (nielsdos) + . Fixed bug GH-15766 (ReflectionClass::toString() should have better output + for enums). (DanielEScherzer) - Session: . session_start() throws a ValueError on option argument if not a hashmap diff --git a/UPGRADING b/UPGRADING index 6d06234403d66..319ed7662f30f 100644 --- a/UPGRADING +++ b/UPGRADING @@ -201,6 +201,11 @@ PHP 8.5 UPGRADE NOTES . posix_fpathconf checks invalid file descriptors and sets last_error to EBADF and raises an E_WARNING message. +- Reflection: + . The output of ReflectionClass::toString() for enums has changed to + better indicate that the class is an enum, and that the enum cases + are enum cases rather than normal class constants. + - Session: . session_start is stricter in regard of the option argument. It throws a ValueError if the whole is not a hashmap or From f994c2f1fa8f3fdca303e8efb1e0d7530d1dcd04 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 26 Mar 2025 19:22:15 +0100 Subject: [PATCH 175/503] Implement benchmark diff commit fallback When the base commit is not benchmarked (yet), iterate first parents of the commit until we find one that is. Fixes GH-18094 Closes GH-18152 --- benchmark/generate_diff.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/benchmark/generate_diff.php b/benchmark/generate_diff.php index b62f55c06d9e4..3a1e0d7b1370f 100644 --- a/benchmark/generate_diff.php +++ b/benchmark/generate_diff.php @@ -10,6 +10,7 @@ function main(?string $headCommitHash, ?string $baseCommitHash) { $repo = __DIR__ . '/repos/data'; cloneRepo($repo, 'git@github.com:php/benchmarking-data.git'); + $baseCommitHash = find_benchmarked_commit_hash($repo, $baseCommitHash); $headSummaryFile = $repo . '/' . substr($headCommitHash, 0, 2) . '/' . $headCommitHash . '/summary.json'; $baseSummaryFile = $repo . '/' . substr($baseCommitHash, 0, 2) . '/' . $baseCommitHash . '/summary.json'; if (!file_exists($headSummaryFile)) { @@ -60,6 +61,24 @@ function formatDiff(?int $baseInstructions, int $headInstructions): string { return sprintf('%.2f%%', $instructionDiff / $baseInstructions * 100); } +function find_benchmarked_commit_hash(string $repo, string $commitHash): ?string { + $repeat = 10; + + while (true) { + if ($repeat-- <= 0) { + fwrite(STDERR, "Count not find benchmarked commit hash\n"); + exit(1); + } + $summaryFile = $repo . '/' . substr($commitHash, 0, 2) . '/' . $commitHash . '/summary.json'; + if (file_exists($summaryFile)) { + break; + } + $commitHash = trim(runCommand(['git', 'rev-parse', $commitHash . '^'], dirname(__DIR__))->stdout); + } + + return $commitHash; +} + $headCommitHash = $argv[1] ?? null; $baseCommitHash = $argv[2] ?? null; $output = main($headCommitHash, $baseCommitHash); From 272f7f75e2d4ff25d4dc00b0102c39fdb4f9c573 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 5 Feb 2025 22:13:25 +0100 Subject: [PATCH 176/503] Fix infinite recursion on deprecated attribute evaluation Fixes GH-17711 Fixes GH-18022 Closes GH-17712 --- NEWS | 3 ++ .../deprecated/class_constants/gh17711.phpt | 28 +++++++++++++++++++ Zend/zend_API.c | 2 +- Zend/zend_compile.c | 4 +++ Zend/zend_constants.c | 4 ++- Zend/zend_constants.h | 11 ++++++++ Zend/zend_vm_def.h | 4 ++- Zend/zend_vm_execute.h | 24 ++++++++++++---- ext/opcache/ZendAccelerator.c | 5 ++++ 9 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 Zend/tests/attributes/deprecated/class_constants/gh17711.phpt diff --git a/NEWS b/NEWS index d747ba1b07b93..1eb60d4b67b5b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.7 +- Core: + . Fixed bug GH-17711 and GH-18022 (Infinite recursion on deprecated attribute + evaluation). (ilutov) 27 Mar 2025, PHP 8.4.6RC1 diff --git a/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt b/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt new file mode 100644 index 0000000000000..abec209343ab3 --- /dev/null +++ b/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-17711: Infinite recursion through deprecated class constants self-referencing through deprecation message +--FILE-- + +--EXPECTF-- +Deprecated: Constant C::C is deprecated, Message in %s on line %d +string(7) "Message" + +Deprecated: Constant D::C is deprecated, test in %s on line %d +string(4) "test" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5aac3c1f7d77c..6e254561d3745 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1439,7 +1439,7 @@ ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_ ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) { if (c->ce == class_type) { - if (Z_TYPE(c->value) == IS_CONSTANT_AST) { + if (Z_TYPE(c->value) == IS_CONSTANT_AST || (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) { new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); memcpy(new_c, c, sizeof(zend_class_constant)); c = new_c; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 832dedc421042..195c65d504374 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8822,6 +8822,10 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as if (deprecated) { ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED; + /* For deprecated constants, we need to flag the zval for recursion + * detection. Make sure the zval is separated out of shm. */ + ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS; + ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } } diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index d453b8bb73717..2145cb1915354 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -353,8 +353,10 @@ ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string * } if (UNEXPECTED(ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) { - if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { + if ((flags & ZEND_FETCH_CLASS_SILENT) == 0 && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { goto failure; } diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index 6f0710c0ce63e..bd759c2891500 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -27,6 +27,17 @@ #define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */ #define CONST_DEPRECATED (1<<2) /* Deprecated */ #define CONST_OWNED (1<<3) /* constant should be destroyed together with class */ +#define CONST_RECURSIVE (1<<4) /* Recursion protection for constant evaluation */ + +#define CONST_IS_RECURSIVE(c) (Z_CONSTANT_FLAGS((c)->value) & CONST_RECURSIVE) +#define CONST_PROTECT_RECURSION(c) \ + do { \ + Z_CONSTANT_FLAGS((c)->value) |= CONST_RECURSIVE; \ + } while (0) +#define CONST_UNPROTECT_RECURSION(c) \ + do { \ + Z_CONSTANT_FLAGS((c)->value) &= ~CONST_RECURSIVE; \ + } while (0) #define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a4fa8063a5bd4..37e0e0fb43d95 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6094,8 +6094,10 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2f6f0af2d872c..5270fc841cd8d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7615,8 +7615,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -8775,8 +8777,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -25874,8 +25878,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -26443,8 +26449,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -35282,8 +35290,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -35641,8 +35651,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); zend_deprecated_class_constant(c, constant_name); + CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 459449d85f23c..f71f43b330ffa 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3800,6 +3800,11 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) { val = &c->value; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { + /* For deprecated constants, we need to flag the zval for recursion + * detection. Make sure the zval is separated out of shm. */ + if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) { + ok = false; + } if (EXPECTED(zend_update_class_constant(c, key, c->ce) == SUCCESS)) { was_changed = changed = true; } else { From 0006522211ea9fcbda0a63ad1bd7adee35f335cd Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Wed, 26 Mar 2025 16:00:34 -0700 Subject: [PATCH 177/503] Reflection: optimize smart_str building - When appending a single character to the string, use `smart_str_appendc()` - When appending a C-string without printf use, use `smart_str_appends()` - When appending just a `zend_string`, use `smart_str_append()` --- ext/reflection/php_reflection.c | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 7aedca43d02ce..5fc4bd6b643b5 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -336,40 +336,40 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const } smart_str_append_printf(str, "%s%s [ ", indent, kind); } - smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "type == ZEND_USER_CLASS) ? "type == ZEND_INTERNAL_CLASS && ce->info.internal.module) { smart_str_append_printf(str, ":%s", ce->info.internal.module->name); } - smart_str_append_printf(str, "> "); + smart_str_appends(str, "> "); if (ce->get_iterator != NULL) { - smart_str_append_printf(str, " "); + smart_str_appends(str, " "); } if (ce->ce_flags & ZEND_ACC_INTERFACE) { - smart_str_append_printf(str, "interface "); + smart_str_appends(str, "interface "); } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - smart_str_append_printf(str, "trait "); + smart_str_appends(str, "trait "); } else if (ce->ce_flags & ZEND_ACC_ENUM) { - smart_str_append_printf(str, "enum "); + smart_str_appends(str, "enum "); } else { if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { - smart_str_append_printf(str, "abstract "); + smart_str_appends(str, "abstract "); } if (ce->ce_flags & ZEND_ACC_FINAL) { - smart_str_append_printf(str, "final "); + smart_str_appends(str, "final "); } if (ce->ce_flags & ZEND_ACC_READONLY_CLASS) { - smart_str_append_printf(str, "readonly "); + smart_str_appends(str, "readonly "); } - smart_str_append_printf(str, "class "); + smart_str_appends(str, "class "); } - smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name)); + smart_str_append(str, ce->name); if (ce->parent) { smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name)); } // Show backing type of enums if ((ce->ce_flags & ZEND_ACC_ENUM) && (ce->enum_backing_type != IS_UNDEF)) { - smart_str_append_printf(str, + smart_str_appends(str, ce->enum_backing_type == IS_STRING ? ": string" : ": int" ); } @@ -386,7 +386,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name)); } } - smart_str_append_printf(str, " ] {\n"); + smart_str_appends(str, " ] {\n"); /* The information where a class is declared is only available for user classes */ if (ce->type == ZEND_USER_CLASS) { @@ -490,12 +490,12 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const if ((mptr->common.fn_flags & ZEND_ACC_STATIC) && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce)) { - smart_str_append_printf(str, "\n"); + smart_str_appendc(str, '\n'); _function_string(str, mptr, ce, ZSTR_VAL(sub_indent)); } } ZEND_HASH_FOREACH_END(); } else { - smart_str_append_printf(str, "\n"); + smart_str_appendc(str, '\n'); } smart_str_append_printf(str, "%s }\n", indent); @@ -566,7 +566,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const smart_str_append_printf(str, "\n%s - Methods [%d] {", indent, count); smart_str_append_smart_str(str, &method_str); if (!count) { - smart_str_append_printf(str, "\n"); + smart_str_appendc(str, '\n'); } smart_str_free(&method_str); } else { @@ -590,7 +590,7 @@ static void _const_string(smart_str *str, const char *name, zval *value, const c if (flags & (CONST_PERSISTENT|CONST_NO_FILE_CACHE|CONST_DEPRECATED)) { bool first = true; - smart_str_appends(str, "<"); + smart_str_appendc(str, '<'); #define DUMP_CONST_FLAG(flag, output) \ do { \ @@ -754,7 +754,7 @@ static int format_default_value(smart_str *str, zval *value) { ZEND_ASSERT(!(class->ce_flags & ZEND_ACC_ENUM)); smart_str_appends(str, "object("); smart_str_append(str, class->name); - smart_str_appends(str, ")"); + smart_str_appendc(str, ')'); } else { ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST); zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), ""); @@ -774,9 +774,9 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_ { smart_str_append_printf(str, "Parameter #%d [ ", offset); if (!required) { - smart_str_append_printf(str, " "); + smart_str_appends(str, " "); } else { - smart_str_append_printf(str, " "); + smart_str_appends(str, " "); } if (ZEND_TYPE_IS_SET(arg_info->type)) { zend_string *type_str = zend_type_to_string(arg_info->type); @@ -862,7 +862,7 @@ static void _function_closure_string(smart_str *str, const zend_function *fptr, return; } - smart_str_append_printf(str, "\n"); + smart_str_appendc(str, '\n'); smart_str_append_printf(str, "%s- Bound Variables [%u] {\n", indent, count); i = 0; ZEND_HASH_MAP_FOREACH_STR_KEY(static_variables, key) { @@ -890,8 +890,8 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent } smart_str_appendl(str, indent, strlen(indent)); - smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ ")); - smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ ")); + smart_str_appends(str, (fptr->type == ZEND_USER_FUNCTION) ? "common.fn_flags & ZEND_ACC_DEPRECATED) { smart_str_appends(str, ", deprecated"); } @@ -1102,7 +1102,7 @@ static void _extension_class_string(zend_class_entry *ce, zend_string *key, smar if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) { /* dump class if it is not an alias */ if (zend_string_equals_ci(ce->name, key)) { - smart_str_append_printf(str, "\n"); + smart_str_appendc(str, '\n'); _class_string(str, ce, NULL, indent); (*num_classes)++; } @@ -1165,7 +1165,7 @@ static void _extension_string(smart_str *str, const zend_module_entry *module, c _extension_ini_string(ini_entry, &str_ini, indent, module->module_number); } ZEND_HASH_FOREACH_END(); if (smart_str_get_len(&str_ini) > 0) { - smart_str_append_printf(str, "\n - INI {\n"); + smart_str_appends(str, "\n - INI {\n"); smart_str_append_smart_str(str, &str_ini); smart_str_append_printf(str, "%s }\n", indent); } @@ -1200,7 +1200,7 @@ static void _extension_string(smart_str *str, const zend_module_entry *module, c if (fptr->common.type==ZEND_INTERNAL_FUNCTION && fptr->internal_function.module == module) { if (first) { - smart_str_append_printf(str, "\n - Functions {\n"); + smart_str_appends(str, "\n - Functions {\n"); first = 0; } _function_string(str, fptr, NULL, " "); From 45d1acf916d2f9b11d27cc49bffc34f636934173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 27 Mar 2025 10:11:44 +0100 Subject: [PATCH 178/503] Zend: Fix reference counting for Closures in const-expr (#17853) * Clean up closure static variable handling * Zend: Fix reference counting for Closures in const-expr Fixes php/php-src#17851 --------- Co-authored-by: Ilija Tovilo --- .../closure_const_expr/attributes.phpt | 4 +- .../attributes_autoload.inc | 9 +++ .../attributes_autoload.phpt | 57 ++++++++++++++ .../closure_const_expr/static_variable.phpt | 77 +++++++++++++++++++ Zend/zend_ast.c | 3 +- Zend/zend_closures.c | 11 +-- Zend/zend_compile.c | 4 +- Zend/zend_opcode.c | 7 -- ext/opcache/zend_file_cache.c | 21 ++++- 9 files changed, 169 insertions(+), 24 deletions(-) create mode 100644 Zend/tests/closures/closure_const_expr/attributes_autoload.inc create mode 100644 Zend/tests/closures/closure_const_expr/attributes_autoload.phpt create mode 100644 Zend/tests/closures/closure_const_expr/static_variable.phpt diff --git a/Zend/tests/closures/closure_const_expr/attributes.phpt b/Zend/tests/closures/closure_const_expr/attributes.phpt index c83b821d12969..e331bc2edd568 100644 --- a/Zend/tests/closures/closure_const_expr/attributes.phpt +++ b/Zend/tests/closures/closure_const_expr/attributes.phpt @@ -8,13 +8,13 @@ reflection #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] class Attr { public function __construct(public Closure $value) { - $value('foo'); + $value('foo'); } } #[Attr(static function () { })] #[Attr(static function (...$args) { - var_dump($args); + var_dump($args); })] class C {} diff --git a/Zend/tests/closures/closure_const_expr/attributes_autoload.inc b/Zend/tests/closures/closure_const_expr/attributes_autoload.inc new file mode 100644 index 0000000000000..48f9b1987cf5d --- /dev/null +++ b/Zend/tests/closures/closure_const_expr/attributes_autoload.inc @@ -0,0 +1,9 @@ + diff --git a/Zend/tests/closures/closure_const_expr/attributes_autoload.phpt b/Zend/tests/closures/closure_const_expr/attributes_autoload.phpt new file mode 100644 index 0000000000000..fa99e8b5abaa3 --- /dev/null +++ b/Zend/tests/closures/closure_const_expr/attributes_autoload.phpt @@ -0,0 +1,57 @@ +--TEST-- +GH-17851: Use-after-free when instantiating autoloaded class with attribute having a Closure parameter. +--EXTENSIONS-- +reflection +--FILE-- +getAttributes() as $reflectionAttribute) { + var_dump($reflectionAttribute->newInstance()); +} + +?> +--EXPECTF-- +object(Attr)#%d (1) { + ["value"]=> + object(Closure)#%d (3) { + ["name"]=> + string(%d) "{closure:%s:%d}" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + } +} +array(1) { + [0]=> + string(3) "foo" +} +object(Attr)#%d (1) { + ["value"]=> + object(Closure)#%d (4) { + ["name"]=> + string(%d) "{closure:%s:%d}" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + ["parameter"]=> + array(1) { + ["$args"]=> + string(10) "" + } + } +} diff --git a/Zend/tests/closures/closure_const_expr/static_variable.phpt b/Zend/tests/closures/closure_const_expr/static_variable.phpt new file mode 100644 index 0000000000000..5aea594d8620b --- /dev/null +++ b/Zend/tests/closures/closure_const_expr/static_variable.phpt @@ -0,0 +1,77 @@ +--TEST-- +Closures in const expressions support static variables. +--FILE-- + +--EXPECTF-- +object(Closure)#%d (4) { + ["name"]=> + string(%d) "{closure:%s:%d}" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(3) + ["static"]=> + array(2) { + ["x"]=> + array(0) { + } + ["i"]=> + int(1) + } +} +array(1) { + [0]=> + int(2) +} +array(2) { + [0]=> + int(2) + [1]=> + int(4) +} +array(3) { + [0]=> + int(2) + [1]=> + int(4) + [2]=> + int(8) +} +object(Closure)#%d (4) { + ["name"]=> + string(%d) "{closure:%s:%d}" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(3) + ["static"]=> + array(2) { + ["x"]=> + array(3) { + [0]=> + int(2) + [1]=> + int(4) + [2]=> + int(8) + } + ["i"]=> + int(8) + } +} diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 1ae7a0ef7a68e..2551f876d4465 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1277,6 +1277,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf) new->attr = old->attr; new->lineno = old->lineno; new->op_array = old->op_array; + function_add_ref((zend_function *)new->op_array); buf = (void*)((char*)buf + sizeof(zend_ast_op_array)); } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) { zend_ast_fcc *old = (zend_ast_fcc*)ast; @@ -1353,7 +1354,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast) } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) { zend_string_release_ex(zend_ast_get_constant_name(ast), 0); } else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) { - /* Nothing to do. */ + destroy_op_array(zend_ast_get_op_array(ast)->op_array); } else if (EXPECTED(zend_ast_is_decl(ast))) { zend_ast_decl *decl = (zend_ast_decl *) ast; diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index e9945b3284cd9..5777e1a34a2b8 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -528,7 +528,6 @@ static void zend_closure_free_storage(zend_object *object) /* {{{ */ /* We don't own the static variables of fake closures. */ if (!(closure->func.op_array.fn_flags & ZEND_ACC_FAKE_CLOSURE)) { zend_destroy_static_vars(&closure->func.op_array); - closure->func.op_array.static_variables = NULL; } destroy_op_array(&closure->func.op_array); } else if (closure->func.type == ZEND_INTERNAL_FUNCTION) { @@ -760,16 +759,14 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en } /* For fake closures, we want to reuse the static variables of the original function. */ + HashTable *ht = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr); if (!is_fake) { - if (closure->func.op_array.static_variables) { - closure->func.op_array.static_variables = - zend_array_dup(closure->func.op_array.static_variables); + if (!ht) { + ht = closure->func.op_array.static_variables; } ZEND_MAP_PTR_INIT(closure->func.op_array.static_variables_ptr, - closure->func.op_array.static_variables); + ht ? zend_array_dup(ht) : NULL); } else if (func->op_array.static_variables) { - HashTable *ht = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr); - if (!ht) { ht = zend_array_dup(func->op_array.static_variables); ZEND_MAP_PTR_SET(func->op_array.static_variables_ptr, ht); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e33990c73bb67..8e4221673c4cf 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8244,9 +8244,6 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_register_seen_symbol(lcname, ZEND_SYMBOL_FUNCTION); switch (level) { - case FUNC_DECL_LEVEL_CONSTEXPR: - zend_add_dynamic_func_def(op_array); - break; case FUNC_DECL_LEVEL_NESTED: { uint32_t func_ref = zend_add_dynamic_func_def(op_array); if (op_array->fn_flags & ZEND_ACC_CLOSURE) { @@ -8261,6 +8258,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, } break; } + case FUNC_DECL_LEVEL_CONSTEXPR: case FUNC_DECL_LEVEL_TOPLEVEL: /* Nothing to do. */ break; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index f32ae13e06793..ce052024ae7a0 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -636,13 +636,6 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) } if (op_array->num_dynamic_func_defs) { for (i = 0; i < op_array->num_dynamic_func_defs; i++) { - /* Closures overwrite static_variables in their copy. - * Make sure to destroy them when the prototype function is destroyed. */ - if (op_array->dynamic_func_defs[i]->static_variables - && (op_array->dynamic_func_defs[i]->fn_flags & ZEND_ACC_CLOSURE)) { - zend_array_destroy(op_array->dynamic_func_defs[i]->static_variables); - op_array->dynamic_func_defs[i]->static_variables = NULL; - } destroy_op_array(op_array->dynamic_func_defs[i]); } efree(op_array->dynamic_func_defs); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index e612dcd80748b..a2346a56d458e 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -242,6 +242,15 @@ static void zend_file_cache_unserialize_zval(zval *zv, zend_persistent_script *script, void *buf); +static void zend_file_cache_serialize_func(zval *zv, + zend_persistent_script *script, + zend_file_cache_metainfo *info, + void *buf); + +static void zend_file_cache_unserialize_func(zval *zv, + zend_persistent_script *script, + void *buf); + static void *zend_file_cache_serialize_interned(zend_string *str, zend_file_cache_metainfo *info) { @@ -364,8 +373,10 @@ static void zend_file_cache_serialize_ast(zend_ast *ast, } } } else if (ast->kind == ZEND_AST_OP_ARRAY) { - /* The op_array itself will be serialized as part of the dynamic_func_defs. */ - SERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array); + zval z; + ZVAL_PTR(&z, zend_ast_get_op_array(ast)->op_array); + zend_file_cache_serialize_func(&z, script, info, buf); + zend_ast_get_op_array(ast)->op_array = Z_PTR(z); } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) { zend_ast_fcc *fcc = (zend_ast_fcc*)ast; ZEND_MAP_PTR_INIT(fcc->fptr, NULL); @@ -1252,8 +1263,10 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast, } } } else if (ast->kind == ZEND_AST_OP_ARRAY) { - /* The op_array itself will be unserialized as part of the dynamic_func_defs. */ - UNSERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array); + zval z; + ZVAL_PTR(&z, zend_ast_get_op_array(ast)->op_array); + zend_file_cache_unserialize_func(&z, script, buf); + zend_ast_get_op_array(ast)->op_array = Z_PTR(z); } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) { zend_ast_fcc *fcc = (zend_ast_fcc*)ast; ZEND_MAP_PTR_NEW(fcc->fptr); From 2197a490f77d018be1517913a54d24029745682c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 26 Mar 2025 22:35:21 +0100 Subject: [PATCH 179/503] Fix GH-18145: basic_globals_ctor initialization This resets all basic globals during ctor and just modifies the ones with a special value. It also switches to using basic_globals_p which what should be used in this context. Closes GH-18156 --- NEWS | 4 ++++ ext/standard/basic_functions.c | 29 +++++++---------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index 22f3d75974629..4b981f7bdd953 100644 --- a/NEWS +++ b/NEWS @@ -55,6 +55,10 @@ PHP NEWS . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) +- Standard: + . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). + (Jakub Zelenka) + - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 36cf727b82a24..99d92af167f0e 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -215,31 +215,16 @@ static void php_putenv_destructor(zval *zv) /* {{{ */ static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */ { - BG(umask) = -1; - BG(user_tick_functions) = NULL; - BG(user_filter_map) = NULL; - BG(serialize_lock) = 0; - - memset(&BG(serialize), 0, sizeof(BG(serialize))); - memset(&BG(unserialize), 0, sizeof(BG(unserialize))); - - memset(&BG(url_adapt_session_ex), 0, sizeof(BG(url_adapt_session_ex))); - memset(&BG(url_adapt_output_ex), 0, sizeof(BG(url_adapt_output_ex))); + memset(basic_globals_p, 0, sizeof(php_basic_globals)); - BG(url_adapt_session_ex).type = 1; - BG(url_adapt_output_ex).type = 0; + basic_globals_p->umask = -1; + basic_globals_p->url_adapt_session_ex.type = 1; - zend_hash_init(&BG(url_adapt_session_hosts_ht), 0, NULL, NULL, 1); - zend_hash_init(&BG(url_adapt_output_hosts_ht), 0, NULL, NULL, 1); - -#if defined(_REENTRANT) - memset(&BG(mblen_state), 0, sizeof(BG(mblen_state))); -#endif - - BG(page_uid) = -1; - BG(page_gid) = -1; + zend_hash_init(&basic_globals_p->url_adapt_session_hosts_ht, 0, NULL, NULL, 1); + zend_hash_init(&basic_globals_p->url_adapt_output_hosts_ht, 0, NULL, NULL, 1); - BG(syslog_device) = NULL; + basic_globals_p->page_uid = -1; + basic_globals_p->page_gid = -1; } /* }}} */ From fe4930612a2f116f229f743a4723bbc735637663 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 27 Mar 2025 11:53:24 +0100 Subject: [PATCH 180/503] [ci skip] Fix NEWS --- NEWS | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 4b981f7bdd953..bee2ce0e09276 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.21 +- Standard: + . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). + (Jakub Zelenka) 10 Apr 2025, PHP 8.3.20 @@ -55,10 +58,6 @@ PHP NEWS . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in ArrayObject). (nielsdos) -- Standard: - . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). - (Jakub Zelenka) - - Treewide: . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos) From 14fc50e73224cd01d3abb7b2181c2f23b33e5fef Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 4 Feb 2025 12:43:33 +0100 Subject: [PATCH 181/503] Add get_error_handler(), get_exception_handler() functions RFC: https://wiki.php.net/rfc/get-error-exception-handler Closes GH-17693 --- NEWS | 1 + UPGRADING | 6 ++ Zend/tests/get_error_handler.phpt | 88 +++++++++++++++++++++++++++ Zend/tests/get_exception_handler.phpt | 87 ++++++++++++++++++++++++++ Zend/zend_builtin_functions.c | 18 ++++++ Zend/zend_builtin_functions.stub.php | 4 ++ Zend/zend_builtin_functions_arginfo.h | 11 +++- 7 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/get_error_handler.phpt create mode 100644 Zend/tests/get_exception_handler.phpt diff --git a/NEWS b/NEWS index d1165539400e7..23bb612c482ca 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,7 @@ PHP NEWS . Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov) . Added the (void) cast to indicate that not using a value is intentional. (timwolla) + . Added get_error_handler(), get_exception_handler() functions. (Arnaud) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/UPGRADING b/UPGRADING index 319ed7662f30f..48fe0f8e9b60b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -244,6 +244,12 @@ PHP 8.5 UPGRADE NOTES 6. New Functions ======================================== +- Core: + . get_error_handler() allows retrieving the current user-defined error handler + function + . get_exception_handler() allows retrieving the current user-defined exception + handler function + - Curl: . curl_multi_get_handles() allows retrieving all CurlHandles current attached to a CurlMultiHandle. This includes both handles added using diff --git a/Zend/tests/get_error_handler.phpt b/Zend/tests/get_error_handler.phpt new file mode 100644 index 0000000000000..abe0b608a4cf9 --- /dev/null +++ b/Zend/tests/get_error_handler.phpt @@ -0,0 +1,88 @@ +--TEST-- +get_error_handler() +--FILE-- +handle(...)); +var_dump(get_error_handler() === $f); + +echo "\nClosure\n"; +set_error_handler($f = function () {}); +var_dump(get_error_handler() === $f); + +echo "\nInvokable\n"; +set_error_handler($object = new Invokable()); +var_dump(get_error_handler() === $object); + +echo "\nStable return value\n"; +var_dump(get_error_handler() === get_error_handler()); + +?> +==DONE== +--EXPECT-- +No error handler +bool(true) + +Function string +bool(true) + +NULL +bool(true) + +Static method array +bool(true) + +Static method string +bool(true) + +Instance method array +bool(true) + +First class callable method +bool(true) + +Closure +bool(true) + +Invokable +bool(true) + +Stable return value +bool(true) +==DONE== diff --git a/Zend/tests/get_exception_handler.phpt b/Zend/tests/get_exception_handler.phpt new file mode 100644 index 0000000000000..05f43db2c0f4c --- /dev/null +++ b/Zend/tests/get_exception_handler.phpt @@ -0,0 +1,87 @@ +--TEST-- +get_exception_handler() +--FILE-- +handle(...)); +var_dump(get_exception_handler() === $f); + +echo "\nClosure\n"; +set_exception_handler($f = function () {}); +var_dump(get_exception_handler() === $f); + +echo "\nInvokable\n"; +set_exception_handler($object = new Invokable()); +var_dump(get_exception_handler() === $object); + +echo "\nStable return value\n"; +var_dump(get_exception_handler() === get_exception_handler()); + +?>==DONE== +--EXPECT-- +No exception handler +bool(true) + +Function string +bool(true) + +NULL +bool(true) + +Static method array +bool(true) + +Static method string +bool(true) + +Instance method array +bool(true) + +First class callable method +bool(true) + +Closure +bool(true) + +Invokable +bool(true) + +Stable return value +bool(true) +==DONE== diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 57ecd1964a7f3..7a07ceadce2e2 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1322,6 +1322,15 @@ ZEND_FUNCTION(restore_error_handler) } /* }}} */ +ZEND_FUNCTION(get_error_handler) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { + RETURN_COPY(&EG(user_error_handler)); + } +} + /* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */ ZEND_FUNCTION(set_exception_handler) { @@ -1368,6 +1377,15 @@ ZEND_FUNCTION(restore_exception_handler) } /* }}} */ +ZEND_FUNCTION(get_exception_handler) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { + RETURN_COPY(&EG(user_exception_handler)); + } +} + static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */ { zend_string *key; diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index f7009c4ffba6e..7f316835aea6b 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -117,11 +117,15 @@ function set_error_handler(?callable $callback, int $error_levels = E_ALL) {} function restore_error_handler(): true {} +function get_error_handler(): ?callable {} + /** @return callable|null */ function set_exception_handler(?callable $callback) {} function restore_exception_handler(): true {} +function get_exception_handler(): ?callable {} + /** * @return array * @refcount 1 diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index cf34b1c0012d5..9498b8292f892 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3dbc84896823c9aaa9ac8aeef8841266920c3e50 */ + * Stub hash: a24761186f1ddf758e648b0a764826537cbd33b9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_exit, 0, 0, IS_NEVER, 0) ZEND_ARG_TYPE_MASK(0, status, MAY_BE_STRING|MAY_BE_LONG, "0") @@ -148,12 +148,17 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, IS_TRUE, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_error_handler, 0, 0, IS_CALLABLE, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1) ZEND_END_ARG_INFO() #define arginfo_restore_exception_handler arginfo_restore_error_handler +#define arginfo_get_exception_handler arginfo_get_error_handler + #define arginfo_get_declared_classes arginfo_func_get_args #define arginfo_get_declared_traits arginfo_func_get_args @@ -272,8 +277,10 @@ ZEND_FUNCTION(get_included_files); ZEND_FUNCTION(trigger_error); ZEND_FUNCTION(set_error_handler); ZEND_FUNCTION(restore_error_handler); +ZEND_FUNCTION(get_error_handler); ZEND_FUNCTION(set_exception_handler); ZEND_FUNCTION(restore_exception_handler); +ZEND_FUNCTION(get_exception_handler); ZEND_FUNCTION(get_declared_classes); ZEND_FUNCTION(get_declared_traits); ZEND_FUNCTION(get_declared_interfaces); @@ -336,8 +343,10 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("user_error", zif_trigger_error, arginfo_user_error, 0, NULL, NULL) ZEND_FE(set_error_handler, arginfo_set_error_handler) ZEND_FE(restore_error_handler, arginfo_restore_error_handler) + ZEND_FE(get_error_handler, arginfo_get_error_handler) ZEND_FE(set_exception_handler, arginfo_set_exception_handler) ZEND_FE(restore_exception_handler, arginfo_restore_exception_handler) + ZEND_FE(get_exception_handler, arginfo_get_exception_handler) ZEND_FE(get_declared_classes, arginfo_get_declared_classes) ZEND_FE(get_declared_traits, arginfo_get_declared_traits) ZEND_FE(get_declared_interfaces, arginfo_get_declared_interfaces) From 26f5009e91eee02fd46d757df86f02b3ebcdca7f Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 13 Mar 2025 12:50:01 +0100 Subject: [PATCH 182/503] Fix lazy proxy calling magic methods twice Fixes GH-18038 Closes GH-18039 --- NEWS | 1 + Zend/tests/lazy_objects/gh18038-001.phpt | 29 +++++++ Zend/tests/lazy_objects/gh18038-002.phpt | 38 +++++++++ Zend/tests/lazy_objects/gh18038-003.phpt | 30 ++++++++ Zend/tests/lazy_objects/gh18038-004.phpt | 45 +++++++++++ Zend/tests/lazy_objects/gh18038-005.phpt | 28 +++++++ Zend/tests/lazy_objects/gh18038-006.phpt | 37 +++++++++ Zend/tests/lazy_objects/gh18038-007.phpt | 41 ++++++++++ Zend/tests/lazy_objects/gh18038-008.phpt | 28 +++++++ Zend/tests/lazy_objects/gh18038-009.phpt | 41 ++++++++++ Zend/tests/lazy_objects/gh18038-010.phpt | 35 +++++++++ Zend/tests/lazy_objects/gh18038-011.phpt | 45 +++++++++++ Zend/tests/lazy_objects/gh18038-012.phpt | 28 +++++++ Zend/zend_object_handlers.c | 98 +++++++++++++++++++----- 14 files changed, 503 insertions(+), 21 deletions(-) create mode 100644 Zend/tests/lazy_objects/gh18038-001.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-002.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-003.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-004.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-005.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-006.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-007.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-008.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-009.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-010.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-011.phpt create mode 100644 Zend/tests/lazy_objects/gh18038-012.phpt diff --git a/NEWS b/NEWS index b2cea7cd533a3..e0916d904edeb 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - Core: . Fixed bug GH-17711 and GH-18022 (Infinite recursion on deprecated attribute evaluation). (ilutov) + . Fixed bug GH-18038 (Lazy proxy calls magic methods twice). (Arnaud) - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). diff --git a/Zend/tests/lazy_objects/gh18038-001.phpt b/Zend/tests/lazy_objects/gh18038-001.phpt new file mode 100644 index 0000000000000..88e453c4a251f --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-001.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-18038 001: Lazy proxy calls magic methods twice +--FILE-- +$name = $value * 2; + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +$obj->prop = 1; +var_dump($obj->prop); + +?> +--EXPECT-- +string(8) "C::__set" +init +int(2) diff --git a/Zend/tests/lazy_objects/gh18038-002.phpt b/Zend/tests/lazy_objects/gh18038-002.phpt new file mode 100644 index 0000000000000..4c12f21de8115 --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-002.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-18038 002: Lazy proxy calls magic methods twice +--FILE-- +$name = $value * 2; + unset($this->$name); + $this->$name = $value * 2; + } +} + +#[AllowDynamicProperties] +class Proxy extends RealInstance { +} + +$rc = new ReflectionClass(Proxy::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new RealInstance; +}); + +$real = $rc->initializeLazyObject($obj); +$real->prop = 1; +var_dump($obj->prop); + +?> +--EXPECT-- +init +string(19) "RealInstance::__set" +string(12) "Proxy::__set" +int(2) diff --git a/Zend/tests/lazy_objects/gh18038-003.phpt b/Zend/tests/lazy_objects/gh18038-003.phpt new file mode 100644 index 0000000000000..1db0588a70cfa --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-003.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-18038 003: Lazy proxy calls magic methods twice +--FILE-- +$name; + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +var_dump($obj->prop); + +?> +--EXPECTF-- +string(8) "C::__get" +init + +Warning: Undefined property: C::$prop in %s on line %d +NULL diff --git a/Zend/tests/lazy_objects/gh18038-004.phpt b/Zend/tests/lazy_objects/gh18038-004.phpt new file mode 100644 index 0000000000000..8810efb6bec2e --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-004.phpt @@ -0,0 +1,45 @@ +--TEST-- +GH-18038 004: Lazy proxy calls magic methods twice +--FILE-- +$name); + return $this->$name; + } +} + +#[AllowDynamicProperties] +class Proxy extends RealInstance { + public function __get($name) { + var_dump(get_class($this)."::".__FUNCTION__); + return $this->$name; + } +} + +$rc = new ReflectionClass(Proxy::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new RealInstance; +}); + +$real = $rc->initializeLazyObject($obj); +var_dump($real->prop); + +?> +--EXPECTF-- +init +string(19) "RealInstance::__get" +string(12) "Proxy::__get" + +Warning: Undefined property: RealInstance::$prop in %s on line %d +NULL + +Warning: Undefined property: RealInstance::$prop in %s on line %d +NULL diff --git a/Zend/tests/lazy_objects/gh18038-005.phpt b/Zend/tests/lazy_objects/gh18038-005.phpt new file mode 100644 index 0000000000000..b728d45253daf --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-005.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-18038 005: Lazy proxy calls magic methods twice +--FILE-- +$name['']); + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +var_dump(isset($obj->prop[''])); + +?> +--EXPECT-- +string(10) "C::__isset" +init +bool(false) diff --git a/Zend/tests/lazy_objects/gh18038-006.phpt b/Zend/tests/lazy_objects/gh18038-006.phpt new file mode 100644 index 0000000000000..256f0be8e202b --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-006.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-18038 006: Lazy proxy calls magic methods twice +--FILE-- +$name['']); + } + public function __get($name) { + var_dump(__METHOD__); + return $this->$name['']; + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +var_dump(isset($obj->prop[''])); + +?> +--EXPECTF-- +string(10) "C::__isset" +string(8) "C::__get" +init + +Warning: Undefined property: C::$prop in %s on line %d + +Warning: Trying to access array offset on null in %s on line %d +bool(false) diff --git a/Zend/tests/lazy_objects/gh18038-007.phpt b/Zend/tests/lazy_objects/gh18038-007.phpt new file mode 100644 index 0000000000000..9925190a19801 --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-007.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-18038 007: Lazy proxy calls magic methods twice +--FILE-- +$name[''])); + return isset($this->$name['']); + } +} + +#[AllowDynamicProperties] +class Proxy extends RealInstance { + public function __isset($name) { + var_dump(get_class($this)."::".__FUNCTION__); + return isset($this->$name['']); + } +} + +$rc = new ReflectionClass(Proxy::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new RealInstance; +}); + +$real = $rc->initializeLazyObject($obj); +var_dump(isset($real->prop[''])); + +?> +--EXPECT-- +init +string(21) "RealInstance::__isset" +string(14) "Proxy::__isset" +bool(false) +bool(false) diff --git a/Zend/tests/lazy_objects/gh18038-008.phpt b/Zend/tests/lazy_objects/gh18038-008.phpt new file mode 100644 index 0000000000000..34d6e766163de --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-008.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-18038 008: Lazy proxy calls magic methods twice +--FILE-- +$name); + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +var_dump(isset($obj->prop)); + +?> +--EXPECT-- +string(10) "C::__isset" +init +bool(false) diff --git a/Zend/tests/lazy_objects/gh18038-009.phpt b/Zend/tests/lazy_objects/gh18038-009.phpt new file mode 100644 index 0000000000000..3c165a71ccffe --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-009.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-18038 009: Lazy proxy calls magic methods twice +--FILE-- +$name)); + return isset($this->$name); + } +} + +#[AllowDynamicProperties] +class Proxy extends RealInstance { + public function __isset($name) { + var_dump(get_class($this)."::".__FUNCTION__); + return isset($this->$name); + } +} + +$rc = new ReflectionClass(Proxy::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new RealInstance; +}); + +$real = $rc->initializeLazyObject($obj); +var_dump(isset($real->prop)); + +?> +--EXPECT-- +init +string(21) "RealInstance::__isset" +string(14) "Proxy::__isset" +bool(false) +bool(false) diff --git a/Zend/tests/lazy_objects/gh18038-010.phpt b/Zend/tests/lazy_objects/gh18038-010.phpt new file mode 100644 index 0000000000000..584c18580a210 --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-010.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-18038 010: Lazy proxy calls magic methods twice +--FILE-- +$name); + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new C; +}); + +unset($obj->prop); +var_dump($obj); + +?> +--EXPECTF-- +string(10) "C::__unset" +init +lazy proxy object(C)#%d (1) { + ["instance"]=> + object(C)#%d (1) { + ["_"]=> + NULL + } +} diff --git a/Zend/tests/lazy_objects/gh18038-011.phpt b/Zend/tests/lazy_objects/gh18038-011.phpt new file mode 100644 index 0000000000000..b356f9e4f384d --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-011.phpt @@ -0,0 +1,45 @@ +--TEST-- +GH-18038 011: Lazy proxy calls magic methods twice +--FILE-- +$name); + } +} + +#[AllowDynamicProperties] +class Proxy extends RealInstance { + public function __isset($name) { + var_dump(get_class($this)."::".__FUNCTION__); + unset($this->$name); + } +} + +$rc = new ReflectionClass(Proxy::class); + +$obj = $rc->newLazyProxy(function () { + echo "init\n"; + return new RealInstance; +}); + +$real = $rc->initializeLazyObject($obj); +unset($real->prop); +var_dump($obj); + +?> +--EXPECTF-- +init +string(21) "RealInstance::__unset" +lazy proxy object(Proxy)#%d (1) { + ["instance"]=> + object(RealInstance)#%d (1) { + ["_"]=> + NULL + } +} diff --git a/Zend/tests/lazy_objects/gh18038-012.phpt b/Zend/tests/lazy_objects/gh18038-012.phpt new file mode 100644 index 0000000000000..5bc83333d81c7 --- /dev/null +++ b/Zend/tests/lazy_objects/gh18038-012.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-18038 012: Lazy proxy calls magic methods twice +--FILE-- +$name = $value * 2; + } +} + +$rc = new ReflectionClass(C::class); + +$obj = $rc->newLazyGhost(function () { + echo "init\n"; +}); + +$obj->prop = 1; +var_dump($obj->prop); + +?> +--EXPECT-- +string(8) "C::__set" +init +int(2) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index a4dba771e3ef5..4aea3501cf269 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -946,6 +946,18 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int goto exit; } + if (UNEXPECTED(guard)) { + uint32_t guard_type = (type == BP_VAR_IS) && zobj->ce->__isset + ? IN_ISSET : IN_GET; + guard = zend_get_property_guard(zobj, name); + if (!((*guard) & guard_type)) { + (*guard) |= guard_type; + retval = zend_std_read_property(zobj, name, type, cache_slot, rv); + (*guard) &= ~guard_type; + return retval; + } + } + return zend_std_read_property(zobj, name, type, cache_slot, rv); } } @@ -970,6 +982,43 @@ static zend_always_inline bool property_uses_strict_types(void) { && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)); } +static zval *forward_write_to_lazy_object(zend_object *zobj, + zend_string *name, zval *value, void **cache_slot, bool guarded) +{ + zval *variable_ptr; + + /* backup value as it may change during initialization */ + zval backup; + ZVAL_COPY(&backup, value); + + zend_object *instance = zend_lazy_object_init(zobj); + if (UNEXPECTED(!instance)) { + zval_ptr_dtor(&backup); + return &EG(error_zval); + } + + if (UNEXPECTED(guarded)) { + uint32_t *guard = zend_get_property_guard(instance, name); + if (!((*guard) & IN_SET)) { + (*guard) |= IN_SET; + variable_ptr = zend_std_write_property(instance, name, &backup, cache_slot); + (*guard) &= ~IN_SET; + goto exit; + } + } + + variable_ptr = zend_std_write_property(instance, name, &backup, cache_slot); + +exit: + zval_ptr_dtor(&backup); + + if (variable_ptr == &backup) { + variable_ptr = value; + } + + return variable_ptr; +} + ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot) /* {{{ */ { zval *variable_ptr, tmp; @@ -1151,7 +1200,8 @@ found:; variable_ptr = value; } else if (EXPECTED(!IS_WRONG_PROPERTY_OFFSET(property_offset))) { if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { - goto lazy_init; + return forward_write_to_lazy_object(zobj, name, value, + cache_slot, /* guarded */ true); } goto write_std_property; @@ -1198,26 +1248,9 @@ found:; exit: return variable_ptr; -lazy_init:; - /* backup value as it may change during initialization */ - zval backup; - ZVAL_COPY(&backup, value); - - zobj = zend_lazy_object_init(zobj); - if (UNEXPECTED(!zobj)) { - variable_ptr = &EG(error_zval); - zval_ptr_dtor(&backup); - goto exit; - } - - variable_ptr = zend_std_write_property(zobj, name, &backup, cache_slot); - zval_ptr_dtor(&backup); - - if (variable_ptr == &backup) { - variable_ptr = value; - } - - return variable_ptr; +lazy_init: + return forward_write_to_lazy_object(zobj, name, value, cache_slot, + /* guarded */ false); } /* }}} */ @@ -1538,6 +1571,17 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void if (!zobj) { return; } + + if (UNEXPECTED(guard)) { + guard = zend_get_property_guard(zobj, name); + if (!((*guard) & IN_UNSET)) { + (*guard) |= IN_UNSET; + zend_std_unset_property(zobj, name, cache_slot); + (*guard) &= ~IN_UNSET; + return; + } + } + zend_std_unset_property(zobj, name, cache_slot); return; } @@ -2323,6 +2367,8 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has } (*guard) &= ~IN_ISSET; OBJ_RELEASE(zobj); + } else { + goto lazy_init; } } @@ -2338,6 +2384,16 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has goto exit; } + if (UNEXPECTED(zobj->ce->__isset)) { + uint32_t *guard = zend_get_property_guard(zobj, name); + if (!((*guard) & IN_ISSET)) { + (*guard) |= IN_ISSET; + result = zend_std_has_property(zobj, name, has_set_exists, cache_slot); + (*guard) &= ~IN_ISSET; + return result; + } + } + return zend_std_has_property(zobj, name, has_set_exists, cache_slot); } } From 3e8677e7e33709d3da37add16d6733446bba489c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 27 Mar 2025 16:22:03 +0100 Subject: [PATCH 183/503] Add missing RFC link in UPGRADING [skip ci] see 14fc50e73224cd01d3abb7b2181c2f23b33e5fef --- UPGRADING | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/UPGRADING b/UPGRADING index 48fe0f8e9b60b..7488912c88804 100644 --- a/UPGRADING +++ b/UPGRADING @@ -246,9 +246,11 @@ PHP 8.5 UPGRADE NOTES - Core: . get_error_handler() allows retrieving the current user-defined error handler - function + function. + RFC: https://wiki.php.net/rfc/get-error-exception-handler . get_exception_handler() allows retrieving the current user-defined exception - handler function + handler function. + RFC: https://wiki.php.net/rfc/get-error-exception-handler - Curl: . curl_multi_get_handles() allows retrieving all CurlHandles current From 9b96ea1a99cc0eaed43ee44c8a8f68b2f6a7786a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Mar 2025 11:51:49 +0100 Subject: [PATCH 184/503] GDB: Import gdb.printing gdb.printing is not imported by default since version 16, for some reason --- main/debug_gdb_scripts.c | 1 + scripts/gdb/php_gdb.py | 1 + 2 files changed, 2 insertions(+) diff --git a/main/debug_gdb_scripts.c b/main/debug_gdb_scripts.c index de7d0c5c92df8..384a1c8b46ee8 100644 --- a/main/debug_gdb_scripts.c +++ b/main/debug_gdb_scripts.c @@ -698,6 +698,7 @@ asm( ".ascii \"\\\"\\\"\\\"\\n\"\n" ".ascii \"\\n\"\n" ".ascii \"import gdb\\n\"\n" + ".ascii \"import gdb.printing\\n\"\n" ".ascii \"import re\\n\"\n" ".ascii \"\\n\"\n" ".ascii \"pp_set = gdb.printing.RegexpCollectionPrettyPrinter(\\\"php\\\")\\n\"\n" diff --git a/scripts/gdb/php_gdb.py b/scripts/gdb/php_gdb.py index 7fef2ad1f49c8..3e40ef8a3b411 100644 --- a/scripts/gdb/php_gdb.py +++ b/scripts/gdb/php_gdb.py @@ -28,6 +28,7 @@ """ import gdb +import gdb.printing import re pp_set = gdb.printing.RegexpCollectionPrettyPrinter("php") From cff76a98ae3901614a3f5c5be70917f9427db175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 27 Mar 2025 20:15:25 +0100 Subject: [PATCH 185/503] zend_smart_string: Add `smart_string_append_printf()` (#18160) This is for API parity with `smart_str_append_printf()`. --- UPGRADING.INTERNALS | 2 ++ Zend/zend_smart_str.c | 7 +++++++ Zend/zend_smart_string.h | 3 +++ 3 files changed, 12 insertions(+) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index d2ab4e13fc52c..13b5e6a394434 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -21,6 +21,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES could interfere. . zend_get_callable_name() now returns the name of the underlying function for fake closures. + . Added smart_string_append_printf() matching smart_str_append_printf() for + char* instead of zend_string*-based smart strings. ======================== 2. Build system changes diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c index ade137a4bb6c3..501f6e6176c8b 100644 --- a/Zend/zend_smart_str.c +++ b/Zend/zend_smart_str.c @@ -131,6 +131,13 @@ ZEND_API void smart_str_append_printf(smart_str *dest, const char *format, ...) va_end(arg); } +ZEND_API void smart_string_append_printf(smart_string *dest, const char *format, ...) { + va_list arg; + va_start(arg, format); + zend_printf_to_smart_string(dest, format, arg); + va_end(arg); +} + #define SMART_STRING_OVERHEAD (ZEND_MM_OVERHEAD + 1) #define SMART_STRING_START_SIZE 256 #define SMART_STRING_START_LEN (SMART_STRING_START_SIZE - SMART_STRING_OVERHEAD) diff --git a/Zend/zend_smart_string.h b/Zend/zend_smart_string.h index 8149b29fb3330..9f04e1a340ad2 100644 --- a/Zend/zend_smart_string.h +++ b/Zend/zend_smart_string.h @@ -48,6 +48,9 @@ #define smart_string_append_unsigned(str, val) \ smart_string_append_unsigned_ex((str), (val), 0) +ZEND_API void smart_string_append_printf(smart_string *dest, const char *format, ...) + ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); + ZEND_API void ZEND_FASTCALL _smart_string_alloc_persistent(smart_string *str, size_t len); ZEND_API void ZEND_FASTCALL _smart_string_alloc(smart_string *str, size_t len); From 2b9840894da4a178585c74ad3b2bfb119890d902 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 27 Mar 2025 22:24:46 +0300 Subject: [PATCH 186/503] Update IR IR commit: dd228777b67334d8ed51de44f427d66d4ac99c08 --- ext/opcache/jit/ir/ir_fold.h | 35 +++++++++++++++- ext/opcache/jit/ir/ir_sccp.c | 57 +++++++++++++------------ ext/opcache/jit/ir/ir_x86.dasc | 76 ++++++++++++++++++++++++++++++---- 3 files changed, 130 insertions(+), 38 deletions(-) diff --git a/ext/opcache/jit/ir/ir_fold.h b/ext/opcache/jit/ir/ir_fold.h index c7745a8c68723..78f3ca0c01e5f 100644 --- a/ext/opcache/jit/ir/ir_fold.h +++ b/ext/opcache/jit/ir/ir_fold.h @@ -1859,8 +1859,39 @@ IR_FOLD(SUB(ADD, ADD)) } // IR_FOLD(SUB(NEG, CONST)) TODO: -a - b => -b - a -// IR_FOLD(MUL(NEG, CONST)) TODO: -a * b => a * -b -// IR_FOLD(DIV(NEG, CONST)) TODO: -a / b => a / -b + +IR_FOLD(MUL(NEG, C_I8)) +IR_FOLD(MUL(NEG, C_I16)) +IR_FOLD(MUL(NEG, C_I32)) +IR_FOLD(MUL(NEG, C_I64)) +IR_FOLD(DIV(NEG, C_I8)) +IR_FOLD(DIV(NEG, C_I16)) +IR_FOLD(DIV(NEG, C_I32)) +IR_FOLD(DIV(NEG, C_I64)) +{ + op1 = op1_insn->op1; + val.i64 = -op2_insn->val.i64; + op2 = ir_const(ctx, val, op2_insn->type); + IR_FOLD_RESTART; +} + +IR_FOLD(MUL(NEG, C_FLOAT)) +IR_FOLD(DIV(NEG, C_FLOAT)) +{ + op1 = op1_insn->op1; + val.f = -op2_insn->val.f; + op2 = ir_const(ctx, val, op2_insn->type); + IR_FOLD_RESTART; +} + +IR_FOLD(MUL(NEG, C_DOUBLE)) +IR_FOLD(DIV(NEG, C_DOUBLE)) +{ + op1 = op1_insn->op1; + val.d = -op2_insn->val.d; + op2 = ir_const(ctx, val, op2_insn->type); + IR_FOLD_RESTART; +} IR_FOLD(MUL(_, C_U8)) IR_FOLD(MUL(_, C_U16)) diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index af039aaef829b..8480861f91fe7 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -1517,7 +1517,7 @@ static bool ir_may_promote_f2d(ir_ctx *ctx, ir_ref ref) return 0; } -static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use) +static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_bitqueue *worklist) { ir_insn *insn = &ctx->ir_base[ref]; uint32_t count; @@ -1526,6 +1526,7 @@ static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use) if (IR_IS_CONST_REF(ref)) { return ir_const_float(ctx, (float)insn->val.d); } else { + ir_bitqueue_add(worklist, ref); switch (insn->op) { case IR_FP2FP: count = ctx->use_lists[ref].count; @@ -1555,7 +1556,7 @@ static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use) // return ref; case IR_NEG: case IR_ABS: - insn->op1 = ir_promote_d2f(ctx, insn->op1, ref); + insn->op1 = ir_promote_d2f(ctx, insn->op1, ref, worklist); insn->type = IR_FLOAT; return ref; case IR_ADD: @@ -1565,10 +1566,10 @@ static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use) case IR_MIN: case IR_MAX: if (insn->op1 == insn->op2) { - insn->op2 = insn->op1 = ir_promote_d2f(ctx, insn->op1, ref); + insn->op2 = insn->op1 = ir_promote_d2f(ctx, insn->op1, ref, worklist); } else { - insn->op1 = ir_promote_d2f(ctx, insn->op1, ref); - insn->op2 = ir_promote_d2f(ctx, insn->op2, ref); + insn->op1 = ir_promote_d2f(ctx, insn->op1, ref, worklist); + insn->op2 = ir_promote_d2f(ctx, insn->op2, ref, worklist); } insn->type = IR_FLOAT; return ref; @@ -1580,7 +1581,7 @@ static ir_ref ir_promote_d2f(ir_ctx *ctx, ir_ref ref, ir_ref use) return ref; } -static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use) +static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_bitqueue *worklist) { ir_insn *insn = &ctx->ir_base[ref]; uint32_t count; @@ -1590,6 +1591,7 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use) if (IR_IS_CONST_REF(ref)) { return ir_const_double(ctx, (double)insn->val.f); } else { + ir_bitqueue_add(worklist, ref); switch (insn->op) { case IR_FP2FP: count = ctx->use_lists[ref].count; @@ -1628,7 +1630,7 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use) return ref; case IR_NEG: case IR_ABS: - insn->op1 = ir_promote_f2d(ctx, insn->op1, ref); + insn->op1 = ir_promote_f2d(ctx, insn->op1, ref, worklist); insn->type = IR_DOUBLE; return ref; case IR_ADD: @@ -1638,10 +1640,10 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use) case IR_MIN: case IR_MAX: if (insn->op1 == insn->op2) { - insn->op2 = insn->op1 = ir_promote_f2d(ctx, insn->op1, ref); + insn->op2 = insn->op1 = ir_promote_f2d(ctx, insn->op1, ref, worklist); } else { - insn->op1 = ir_promote_f2d(ctx, insn->op1, ref); - insn->op2 = ir_promote_f2d(ctx, insn->op2, ref); + insn->op1 = ir_promote_f2d(ctx, insn->op1, ref, worklist); + insn->op2 = ir_promote_f2d(ctx, insn->op2, ref, worklist); } insn->type = IR_DOUBLE; return ref; @@ -1707,7 +1709,7 @@ static bool ir_may_promote_trunc(ir_ctx *ctx, ir_type type, ir_ref ref) } } } - for (p = insn->ops + 1, n = insn->inputs_count - 1; n > 0; p++, n--) { + for (p = insn->ops + 2, n = insn->inputs_count - 1; n > 0; p++, n--) { input = *p; if (input != ref) { if (!ir_may_promote_trunc(ctx, type, input)) { @@ -1723,7 +1725,7 @@ static bool ir_may_promote_trunc(ir_ctx *ctx, ir_type type, ir_ref ref) return 0; } -static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) +static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use, ir_bitqueue *worklist) { ir_insn *insn = &ctx->ir_base[ref]; uint32_t count; @@ -1732,6 +1734,7 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) if (IR_IS_CONST_REF(ref)) { return ir_const(ctx, insn->val, type); } else { + ir_bitqueue_add(worklist, ref); switch (insn->op) { case IR_ZEXT: case IR_SEXT: @@ -1776,7 +1779,7 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) case IR_NEG: case IR_ABS: case IR_NOT: - insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref); + insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref, worklist); insn->type = type; return ref; case IR_ADD: @@ -1789,10 +1792,10 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) case IR_XOR: case IR_SHL: if (insn->op1 == insn->op2) { - insn->op2 = insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref); + insn->op2 = insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref, worklist); } else { - insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref); - insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref); + insn->op1 = ir_promote_i2i(ctx, type, insn->op1, ref, worklist); + insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref, worklist); } insn->type = type; return ref; @@ -1804,18 +1807,18 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use) // TODO: ??? case IR_COND: if (insn->op2 == insn->op3) { - insn->op3 = insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref); + insn->op3 = insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref, worklist); } else { - insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref); - insn->op3 = ir_promote_i2i(ctx, type, insn->op3, ref); + insn->op2 = ir_promote_i2i(ctx, type, insn->op2, ref, worklist); + insn->op3 = ir_promote_i2i(ctx, type, insn->op3, ref, worklist); } insn->type = type; return ref; case IR_PHI: - for (p = insn->ops + 1, n = insn->inputs_count - 1; n > 0; p++, n--) { + for (p = insn->ops + 2, n = insn->inputs_count - 1; n > 0; p++, n--) { input = *p; if (input != ref) { - *p = ir_promote_i2i(ctx, type, input, ref); + *p = ir_promote_i2i(ctx, type, input, ref, worklist); } } insn->type = type; @@ -1906,7 +1909,7 @@ static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val) } IR_ASSERT(ir_op_flags[insn->op] & IR_OP_FLAG_DATA); - if (IR_OPND_KIND(ir_op_flags[insn->op], 1) & IR_OPND_CONTROL_DEP) { + if (IR_OPND_KIND(ir_op_flags[insn->op], 1) == IR_OPND_CONTROL_DEP) { return insn->op1; } @@ -3479,14 +3482,14 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist) case IR_FP2FP: if (insn->type == IR_FLOAT) { if (ir_may_promote_d2f(ctx, insn->op1)) { - ir_ref ref = ir_promote_d2f(ctx, insn->op1, i); + ir_ref ref = ir_promote_d2f(ctx, insn->op1, i, worklist); insn->op1 = ref; ir_iter_replace_insn(ctx, i, ref, worklist); break; } } else { if (ir_may_promote_f2d(ctx, insn->op1)) { - ir_ref ref = ir_promote_f2d(ctx, insn->op1, i); + ir_ref ref = ir_promote_f2d(ctx, insn->op1, i, worklist); insn->op1 = ref; ir_iter_replace_insn(ctx, i, ref, worklist); break; @@ -3496,17 +3499,17 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist) case IR_FP2INT: if (ctx->ir_base[insn->op1].type == IR_DOUBLE) { if (ir_may_promote_d2f(ctx, insn->op1)) { - insn->op1 = ir_promote_d2f(ctx, insn->op1, i); + insn->op1 = ir_promote_d2f(ctx, insn->op1, i, worklist); } } else { if (ir_may_promote_f2d(ctx, insn->op1)) { - insn->op1 = ir_promote_f2d(ctx, insn->op1, i); + insn->op1 = ir_promote_f2d(ctx, insn->op1, i, worklist); } } goto folding; case IR_TRUNC: if (ir_may_promote_trunc(ctx, insn->type, insn->op1)) { - ir_ref ref = ir_promote_i2i(ctx, insn->type, insn->op1, i); + ir_ref ref = ir_promote_i2i(ctx, insn->type, insn->op1, i, worklist); insn->op1 = ref; ir_iter_replace_insn(ctx, i, ref, worklist); break; diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index 3b6cf156ad909..ad785d3b891eb 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -1003,6 +1003,8 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(LEA_SI_B) \ _(LEA_B_SI_O) \ _(LEA_SI_B_O) \ + _(LEA_SYM_O) \ + _(LEA_O_SYM) \ _(INC) \ _(DEC) \ _(MUL_PWR2) \ @@ -1065,6 +1067,9 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(SSE_TRUNC) \ _(SSE_NEARBYINT) \ +#define IR_LEA_FIRST IR_LEA_OB +#define IR_LEA_LAST IR_LEA_O_SYM + #define IR_RULE_ENUM(name) IR_ ## name, #define IR_STATIC_ALLOCA (IR_SKIPPED | IR_FUSED | IR_SIMPLE | IR_ALLOCA) @@ -1584,7 +1589,7 @@ static void ir_match_fuse_addr(ir_ctx *ctx, ir_ref addr_ref) if (!rule) { ctx->rules[addr_ref] = rule = ir_match_insn(ctx, addr_ref); } - if (rule >= IR_LEA_OB && rule <= IR_LEA_SI_B_O) { + if (rule >= IR_LEA_FIRST && rule <= IR_LEA_LAST) { ir_use_list *use_list; ir_ref j; @@ -1972,6 +1977,19 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref) if ((ctx->flags & IR_OPT_CODEGEN) && IR_IS_CONST_REF(insn->op2)) { op2_insn = &ctx->ir_base[insn->op2]; if (IR_IS_CONST_REF(insn->op1)) { + ir_insn *op1_insn = &ctx->ir_base[insn->op1]; + + if (insn->op == IR_ADD + && IR_IS_SYM_CONST(op1_insn->op) + && !IR_IS_SYM_CONST(op2_insn->op) + && IR_IS_SIGNED_32BIT((intptr_t)ir_sym_val(ctx, op1_insn) + (intptr_t)op2_insn->val.i64)) { + return IR_LEA_SYM_O; + } else if (insn->op == IR_ADD + && IR_IS_SYM_CONST(op2_insn->op) + && !IR_IS_SYM_CONST(op1_insn->op) + && IR_IS_SIGNED_32BIT((intptr_t)ir_sym_val(ctx, op2_insn) + (intptr_t)op1_insn->val.i64)) { + return IR_LEA_O_SYM; + } // const // TODO: add support for sym+offset ??? } else if (IR_IS_SYM_CONST(op2_insn->op)) { @@ -3264,7 +3282,11 @@ static void ir_emit_mov_ext(ir_ctx *ctx, ir_type type, ir_reg dst, ir_reg src) | ASM_REG_REG_OP mov, type, dst, src } else if (ir_type_size[type] == 2) { if (IR_IS_TYPE_SIGNED(type)) { - | movsx Rd(dst), Rw(src) + if (dst == IR_REG_RAX && src == IR_REG_RAX) { + | cwde + } else { + | movsx Rd(dst), Rw(src) + } } else { | movzx Rd(dst), Rw(src) } @@ -3311,8 +3333,8 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) ir_reg base_reg = IR_REG_NONE, index_reg; int32_t offset = 0, scale; - IR_ASSERT(((rule & IR_RULE_MASK) >= IR_LEA_OB && - (rule & IR_RULE_MASK) <= IR_LEA_SI_B_O) || + IR_ASSERT(((rule & IR_RULE_MASK) >= IR_LEA_FIRST && + (rule & IR_RULE_MASK) <= IR_LEA_LAST) || rule == IR_STATIC_ALLOCA); switch (rule & IR_RULE_MASK) { default: @@ -3498,6 +3520,22 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) op1_insn = &ctx->ir_base[op1_insn->op1]; scale = ctx->ir_base[op1_insn->op2].val.i32; break; + case IR_LEA_SYM_O: + op1_insn = &ctx->ir_base[insn->op1]; + op2_insn = &ctx->ir_base[insn->op2]; + offset = (intptr_t)ir_sym_val(ctx, op1_insn) + (intptr_t)op2_insn->val.i64; + base_reg_ref = index_reg_ref = IR_UNUSED; + scale = 1; + offset_insn = NULL; + break; + case IR_LEA_O_SYM: + op1_insn = &ctx->ir_base[insn->op1]; + op2_insn = &ctx->ir_base[insn->op2]; + offset = (intptr_t)ir_sym_val(ctx, op2_insn) + (intptr_t)op1_insn->val.i64; + base_reg_ref = index_reg_ref = IR_UNUSED; + scale = 1; + offset_insn = NULL; + break; case IR_ALLOCA: offset = IR_SPILL_POS_TO_OFFSET(insn->op3); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; @@ -5186,7 +5224,7 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else if (ir_type_size[type] == 2) { | cwd } else { - | movsx ax, al + | cbw } if (op2_reg != IR_REG_NONE) { | ASM_REG_OP idiv, type, op2_reg @@ -6813,7 +6851,11 @@ static void ir_emit_sext(ir_ctx *ctx, ir_ref def, ir_insn *insn) } if (ir_type_size[src_type] == 1) { if (ir_type_size[dst_type] == 2) { - | movsx Rw(def_reg), Rb(op1_reg) + if (def_reg == IR_REG_RAX && op1_reg == IR_REG_RAX) { + | cbw + } else { + | movsx Rw(def_reg), Rb(op1_reg) + } } else if (ir_type_size[dst_type] == 4) { | movsx Rd(def_reg), Rb(op1_reg) } else { @@ -6825,7 +6867,11 @@ static void ir_emit_sext(ir_ctx *ctx, ir_ref def, ir_insn *insn) } } else if (ir_type_size[src_type] == 2) { if (ir_type_size[dst_type] == 4) { - | movsx Rd(def_reg), Rw(op1_reg) + if (def_reg == IR_REG_RAX && op1_reg == IR_REG_RAX) { + | cwde + } else { + | movsx Rd(def_reg), Rw(op1_reg) + } } else { IR_ASSERT(ir_type_size[dst_type] == 8); IR_ASSERT(sizeof(void*) == 8); @@ -6838,7 +6884,11 @@ static void ir_emit_sext(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(ir_type_size[dst_type] == 8); IR_ASSERT(sizeof(void*) == 8); |.if X64 - | movsxd Rq(def_reg), Rd(op1_reg) + if (def_reg == IR_REG_RAX && op1_reg == IR_REG_RAX) { + | cdqe + } else { + | movsxd Rq(def_reg), Rd(op1_reg) + } |.endif } } else if (IR_IS_CONST_REF(insn->op1)) { @@ -7203,6 +7253,8 @@ static void ir_emit_int2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) |.else || if (ir_type_size[src_type] == 1) { | movsx Rd(op1_reg), Rb(op1_reg) +|| } else if (op1_reg == IR_REG_RAX) { + | cwde || } else { | movsx Rd(op1_reg), Rw(op1_reg) || } @@ -8502,7 +8554,11 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) case 4: |.if X64 if (IR_IS_TYPE_SIGNED(type)) { - | movsxd Ra(op2_reg), Rd(op2_reg) + if (op2_reg == IR_REG_RAX) { + | cdqe + } else { + | movsxd Ra(op2_reg), Rd(op2_reg) + } } else { | mov Rd(op2_reg), Rd(op2_reg) } @@ -10603,6 +10659,8 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) case IR_LEA_SI_B: case IR_LEA_B_SI_O: case IR_LEA_SI_B_O: + case IR_LEA_SYM_O: + case IR_LEA_O_SYM: ir_emit_lea(ctx, i, insn->type); break; case IR_MUL_PWR2: From 370f24290f5d204ad3b1625b02a73d1fc64ea11a Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 27 Mar 2025 21:38:52 +0000 Subject: [PATCH 187/503] [ci skip] Fix example and add NEWS merging info to release process (#18159) --- docs/release-process.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/release-process.md b/docs/release-process.md index 46557524988c5..36963b4318ead 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -257,7 +257,7 @@ slightly different steps. We'll call attention where the steps differ. For example, if the RC is `8.2.1RC1` then the version numbers in the version branch should be bumped to `8.2.2-dev`. We do this regardless of whether we build a new RC to make sure `version_compare()` works correctly. See - [Bump for 8.1.8-dev][] for a real example. + [PHP 8.3 is now for PHP 8.3.21-dev][] commit for a real example. Commit the changes to the version branch. @@ -291,6 +291,11 @@ slightly different steps. We'll call attention where the steps differ. > > Local-only release branches should not be pushed! + Do not forget to merge up PHP-X.Y all the way to master. When resolving + the conflicts, ignore the changes from PHP-X.Y in higher branches. It + means using something like `git checkout --ours .` when on PHP.X.Y+1 or + master after the merge resulting in the conflicts. + 11. Run the following using the release tag to export the tree, create the `configure` script, and build and compress three tarballs (`.tar.gz`, `.tar.bz2` and `.tar.xz`). @@ -1098,7 +1103,7 @@ volunteers to begin the selection process for the next release managers. [Prepare for PHP 8.1.0RC1]: https://github.com/php/php-src/commit/5764414eb8900ae98020a3c20693f4fb793efa99 [Update NEWS for PHP 8.2.0 alpha2]: https://github.com/php/php-src/commit/418f7211f71658d79d934861be20f277db96fe2c [Update NEWS for PHP 8.2.0RC6]: https://github.com/php/php-src/commit/4ccc414961a70200d638ca281a35f893226d74e2 -[Bump for 8.1.8-dev]: https://github.com/php/php-src/commit/3b6ee1eb19c14c3339ebfcf5c967065a9f828971 +[PHP 8.3 is now for PHP 8.3.21-dev]: https://github.com/php/php-src/commit/b57f425cfe20a11003253427424cc0517483550b [GitHub command line tool]: https://cli.github.com [Announce 8.1.0RC3]: https://github.com/php/web-qa/commit/f264b711fd3827803b79bbb342959eae57ea502b [8.1.6RC1]: https://github.com/php/web-qa/commit/e6d61ad7a9d8be0b1cd159af29f3b9cbdde33384 From 0943b8b7ebac8303f9093a0f7f7c590b372f8293 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 27 Mar 2025 23:52:54 +0100 Subject: [PATCH 188/503] Improve performance of array_find() etc (#18157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids destruction logic for the common case, avoids some copy, and adds an optimization hint. For this script: ```php $array = range(1, 10000); $result = 0; for ($i = 0; $i < 5000; $i++) { $result += array_find($array, static function ($item) { return $item === 5000; }); } var_dump($result); ``` On an intel i7 1185G7: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 543.7 ms ± 3.8 ms [User: 538.9 ms, System: 4.4 ms] Range (min … max): 538.4 ms … 552.9 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 583.0 ms ± 4.2 ms [User: 578.4 ms, System: 3.4 ms] Range (min … max): 579.3 ms … 593.9 ms 10 runs Summary ./sapi/cli/php x.php ran 1.07 ± 0.01 times faster than ./sapi/cli/php_old x.php ``` On an intel i7 4790: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 828.6 ms ± 4.8 ms [User: 824.4 ms, System: 1.6 ms] Range (min … max): 822.8 ms … 839.0 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 940.1 ms ± 26.4 ms [User: 934.4 ms, System: 2.5 ms] Range (min … max): 918.0 ms … 981.1 ms 10 runs Summary ./sapi/cli/php x.php ran 1.13 ± 0.03 times faster than ./sapi/cli/php_old x.php ``` --- ext/standard/array.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 8462492651310..d26e238180262 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6509,6 +6509,22 @@ PHP_FUNCTION(array_reduce) } /* }}} */ +/* Consumes `zv` */ +static bool php_is_true(zval *zv) +{ + switch (Z_TYPE_P(zv)) { + case IS_TRUE: + return true; + case IS_FALSE: + return false; + default: { + bool rv = zend_is_true(zv); + zval_ptr_dtor(zv); + return rv; + } + } +} + /* {{{ Filters elements from the array via the callback. */ PHP_FUNCTION(array_filter) { @@ -6571,9 +6587,7 @@ PHP_FUNCTION(array_filter) RETURN_THROWS(); } - bool retval_true = zend_is_true(&retval); - zval_ptr_dtor(&retval); - if (!retval_true) { + if (!php_is_true(&retval)) { continue; } } else if (!zend_is_true(operand)) { @@ -6597,7 +6611,7 @@ enum php_array_find_result { PHP_ARRAY_FIND_SOME = 1, }; -static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache fci_cache, zval *result_key, zval *result_value, bool negate_condition) +static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache *fci_cache, zval *result_key, zval *result_value, bool negate_condition) { zend_ulong num_key; zend_string *str_key; @@ -6620,25 +6634,22 @@ static enum php_array_find_result php_array_find(const HashTable *array, zend_fc if (!str_key) { ZVAL_LONG(&args[1], num_key); } else { + /* Allows copying the numeric branch, without this branch, into the iteration code + * that checks for the packed array flag. */ + ZEND_ASSUME(!HT_IS_PACKED(array)); ZVAL_STR(&args[1], str_key); } ZVAL_COPY_VALUE(&args[0], operand); - zend_result result = zend_call_function(&fci, &fci_cache); + zend_result result = zend_call_function(&fci, fci_cache); ZEND_ASSERT(result == SUCCESS); if (UNEXPECTED(Z_ISUNDEF(retval))) { return PHP_ARRAY_FIND_EXCEPTION; } - bool retval_true = zend_is_true(&retval); - zval_ptr_dtor(&retval); - - /* This negates the condition, if negate_condition is true. Otherwise it does nothing with `retval_true`. */ - retval_true ^= negate_condition; - - if (retval_true) { + if (php_is_true(&retval) ^ negate_condition) { if (result_value != NULL) { ZVAL_COPY_DEREF(result_value, &args[0]); } @@ -6667,7 +6678,7 @@ PHP_FUNCTION(array_find) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - php_array_find(array, fci, fci_cache, NULL, return_value, false); + php_array_find(array, fci, &fci_cache, NULL, return_value, false); } /* }}} */ @@ -6683,7 +6694,7 @@ PHP_FUNCTION(array_find_key) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - php_array_find(array, fci, fci_cache, return_value, NULL, false); + php_array_find(array, fci, &fci_cache, return_value, NULL, false); } /* }}} */ @@ -6699,7 +6710,7 @@ PHP_FUNCTION(array_any) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME); + RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME); } /* }}} */ @@ -6715,7 +6726,7 @@ PHP_FUNCTION(array_all) Z_PARAM_FUNC(fci, fci_cache) ZEND_PARSE_PARAMETERS_END(); - RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE); + RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE); } /* }}} */ From c67e12e71843b76a5dd259710d28f5649bd067fa Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 13 Mar 2025 15:05:39 +0000 Subject: [PATCH 189/503] ext/date: Use Z_PARAM_ARRAY_HT instead of Z_PARAM_ARRAY --- ext/date/php_date.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index ed89c9d494a6f..93cdf29eb3104 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2978,15 +2978,13 @@ PHP_METHOD(DateTime, __unserialize) { zval *object = ZEND_THIS; php_date_obj *dateobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); dateobj = Z_PHPDATE_P(object); - myht = Z_ARRVAL_P(array); if (!php_date_initialize_from_hash(&dateobj, myht)) { zend_throw_error(NULL, "Invalid serialization data for DateTime object"); @@ -3002,15 +3000,13 @@ PHP_METHOD(DateTimeImmutable, __unserialize) { zval *object = ZEND_THIS; php_date_obj *dateobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); dateobj = Z_PHPDATE_P(object); - myht = Z_ARRVAL_P(array); if (!php_date_initialize_from_hash(&dateobj, myht)) { zend_throw_error(NULL, "Invalid serialization data for DateTimeImmutable object"); @@ -4087,15 +4083,12 @@ static bool php_date_timezone_initialize_from_hash(zval **return_value, php_time PHP_METHOD(DateTimeZone, __set_state) { php_timezone_obj *tzobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); - myht = Z_ARRVAL_P(array); - php_date_instantiate(date_ce_timezone, return_value); tzobj = Z_PHPTIMEZONE_P(return_value); if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) { @@ -4174,15 +4167,13 @@ PHP_METHOD(DateTimeZone, __unserialize) { zval *object = ZEND_THIS; php_timezone_obj *tzobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); tzobj = Z_PHPTIMEZONE_P(object); - myht = Z_ARRVAL_P(array); if (!php_date_timezone_initialize_from_hash(&object, &tzobj, myht)) { zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object"); @@ -4738,15 +4729,12 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte PHP_METHOD(DateInterval, __set_state) { php_interval_obj *intobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); - myht = Z_ARRVAL_P(array); - php_date_instantiate(date_ce_interval, return_value); intobj = Z_PHPINTERVAL_P(return_value); php_date_interval_initialize_from_hash(&return_value, &intobj, myht); @@ -4812,15 +4800,13 @@ PHP_METHOD(DateInterval, __unserialize) { zval *object = ZEND_THIS; php_interval_obj *intervalobj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); intervalobj = Z_PHPINTERVAL_P(object); - myht = Z_ARRVAL_P(array); php_date_interval_initialize_from_hash(&object, &intervalobj, myht); restore_custom_dateinterval_properties(object, myht); @@ -5835,15 +5821,12 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, Has PHP_METHOD(DatePeriod, __set_state) { php_period_obj *period_obj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); - myht = Z_ARRVAL_P(array); - object_init_ex(return_value, date_ce_period); period_obj = Z_PHPPERIOD_P(return_value); if (!php_date_period_initialize_from_hash(period_obj, myht)) { @@ -5912,15 +5895,13 @@ PHP_METHOD(DatePeriod, __unserialize) { zval *object = ZEND_THIS; php_period_obj *period_obj; - zval *array; HashTable *myht; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(array) + Z_PARAM_ARRAY_HT(myht) ZEND_PARSE_PARAMETERS_END(); period_obj = Z_PHPPERIOD_P(object); - myht = Z_ARRVAL_P(array); if (!php_date_period_initialize_from_hash(period_obj, myht)) { zend_throw_error(NULL, "Invalid serialization data for DatePeriod object"); From a4685d8b54451281dd78038aabbfa4d57b952fb5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 13 Mar 2025 14:51:49 +0000 Subject: [PATCH 190/503] ext/date: Add const qualifiers --- ext/date/php_date.c | 58 ++++++++++++++++++++++----------------------- ext/date/php_date.h | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 93cdf29eb3104..913f2b032f73d 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -673,7 +673,7 @@ static const char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib /* }}} */ /* {{{ date_format - (gm)date helper */ -static zend_string *date_format(const char *format, size_t format_len, timelib_time *t, bool localtime) +static zend_string *date_format(const char *format, size_t format_len, const timelib_time *t, bool localtime) { smart_str string = {0}; size_t i; @@ -845,7 +845,7 @@ static zend_string *date_format(const char *format, size_t format_len, timelib_t return string.s; } -PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, php_date_obj *date_obj) +PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, const php_date_obj *date_obj) { if (!date_obj->time) { return NULL; @@ -2807,7 +2807,7 @@ PHP_METHOD(DateTimeImmutable, createFromTimestamp) } /* }}} */ -static bool php_date_initialize_from_hash(php_date_obj **dateobj, HashTable *myht) +static bool php_date_initialize_from_hash(php_date_obj **dateobj, const HashTable *myht) { zval *z_date; zval *z_timezone_type; @@ -2948,7 +2948,7 @@ PHP_METHOD(DateTimeImmutable, __serialize) } /* }}} */ -static bool date_time_is_internal_property(zend_string *name) +static bool date_time_is_internal_property(const zend_string *name) { if ( zend_string_equals_literal(name, "date") || @@ -2960,7 +2960,7 @@ static bool date_time_is_internal_property(zend_string *name) return 0; } -static void restore_custom_datetime_properties(zval *object, HashTable *myht) +static void restore_custom_datetime_properties(zval *object, const HashTable *myht) { zend_string *prop_name; zval *prop_val; @@ -3023,7 +3023,7 @@ static void php_do_date_time_wakeup(INTERNAL_FUNCTION_PARAMETERS, const char *cl { zval *object = ZEND_THIS; php_date_obj *dateobj; - HashTable *myht; + const HashTable *myht; ZEND_PARSE_PARAMETERS_NONE(); @@ -3053,7 +3053,7 @@ PHP_METHOD(DateTimeImmutable, __wakeup) /* }}} */ /* Helper function used to add an associative array of warnings and errors to a zval */ -static void zval_from_error_container(zval *z, timelib_error_container *error) /* {{{ */ +static void zval_from_error_container(zval *z, const timelib_error_container *error) /* {{{ */ { int i; zval element; @@ -3494,7 +3494,7 @@ PHP_METHOD(DateTimeImmutable, sub) } /* }}} */ -static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t) +static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, const timelib_time *t) { /* Free abbreviation if already set */ if (tzobj->initialized && tzobj->type == TIMELIB_ZONETYPE_ABBR) { @@ -4053,7 +4053,7 @@ PHP_METHOD(DateTimeZone, __construct) } /* }}} */ -static bool php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */ +static bool php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, const HashTable *myht) /* {{{ */ { zval *z_timezone_type; @@ -4103,7 +4103,7 @@ PHP_METHOD(DateTimeZone, __wakeup) { zval *object = ZEND_THIS; php_timezone_obj *tzobj; - HashTable *myht; + const HashTable *myht; ZEND_PARSE_PARAMETERS_NONE(); @@ -4138,7 +4138,7 @@ PHP_METHOD(DateTimeZone, __serialize) } /* }}} */ -static bool date_timezone_is_internal_property(zend_string *name) +static bool date_timezone_is_internal_property(const zend_string *name) { if ( zend_string_equals_literal(name, "timezone_type") || @@ -4149,7 +4149,7 @@ static bool date_timezone_is_internal_property(zend_string *name) return 0; } -static void restore_custom_datetimezone_properties(zval *object, HashTable *myht) +static void restore_custom_datetimezone_properties(zval *object, const HashTable *myht) { zend_string *prop_name; zval *prop_val; @@ -4413,7 +4413,7 @@ PHP_FUNCTION(timezone_location_get) } /* }}} */ -static bool date_interval_initialize(timelib_rel_time **rt, /*const*/ char *format, size_t format_length) /* {{{ */ +static bool date_interval_initialize(timelib_rel_time **rt, const char *format, size_t format_length) /* {{{ */ { timelib_time *b = NULL, *e = NULL; timelib_rel_time *p = NULL; @@ -4598,10 +4598,10 @@ PHP_METHOD(DateInterval, __construct) } /* }}} */ -static void php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht) /* {{{ */ +static void php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, const HashTable *myht) /* {{{ */ { /* If we have a date_string, use that instead */ - zval *date_str = zend_hash_str_find(myht, "date_string", strlen("date_string")); + const zval *date_str = zend_hash_str_find(myht, "date_string", strlen("date_string")); if (date_str && Z_TYPE_P(date_str) == IS_STRING) { timelib_time *time; timelib_error_container *err = NULL; @@ -4699,7 +4699,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1) { - zval *z_arg = zend_hash_str_find(myht, "f", sizeof("f") - 1); + const zval *z_arg = zend_hash_str_find(myht, "f", sizeof("f") - 1); if (z_arg) { (*intobj)->diff->us = zend_dval_to_lval(zval_get_double(z_arg) * 1000000.0); } @@ -4714,7 +4714,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0); PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0); { - zval *z_arg = zend_hash_str_find(myht, "civil_or_wall", sizeof("civil_or_wall") - 1); + const zval *z_arg = zend_hash_str_find(myht, "civil_or_wall", sizeof("civil_or_wall") - 1); (*intobj)->civil_or_wall = PHP_DATE_CIVIL; if (z_arg) { zend_long val = zval_get_long(z_arg); @@ -4761,7 +4761,7 @@ PHP_METHOD(DateInterval, __serialize) } /* }}} */ -static bool date_interval_is_internal_property(zend_string *name) +static bool date_interval_is_internal_property(const zend_string *name) { if ( zend_string_equals_literal(name, "date_string") || @@ -4781,7 +4781,7 @@ static bool date_interval_is_internal_property(zend_string *name) return 0; } -static void restore_custom_dateinterval_properties(zval *object, HashTable *myht) +static void restore_custom_dateinterval_properties(zval *object, const HashTable *myht) { zend_string *prop_name; zval *prop_val; @@ -4818,7 +4818,7 @@ PHP_METHOD(DateInterval, __wakeup) { zval *object = ZEND_THIS; php_interval_obj *intobj; - HashTable *myht; + const HashTable *myht; ZEND_PARSE_PARAMETERS_NONE(); @@ -4910,7 +4910,7 @@ PHP_METHOD(DateInterval, createFromDateString) /* }}} */ /* {{{ date_interval_format - */ -static zend_string *date_interval_format(char *format, size_t format_len, timelib_rel_time *t) +static zend_string *date_interval_format(const char *format, size_t format_len, timelib_rel_time *t) { smart_str string = {0}; size_t i; @@ -4984,7 +4984,7 @@ PHP_FUNCTION(date_interval_format) { zval *object; php_interval_obj *diobj; - char *format; + const char *format; size_t format_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_interval, &format, &format_len) == FAILURE) { @@ -4997,7 +4997,7 @@ PHP_FUNCTION(date_interval_format) } /* }}} */ -static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib_rel_time **d, zend_long *recurrences, /*const*/ char *format, size_t format_length) /* {{{ */ +static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib_rel_time **d, zend_long *recurrences, const char *format, size_t format_length) /* {{{ */ { timelib_time *b = NULL, *e = NULL; timelib_rel_time *p = NULL; @@ -5030,7 +5030,7 @@ static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib return retval; } /* }}} */ -static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_entry* base_ce, char *isostr, size_t isostr_len, zend_long options, zend_long *recurrences) +static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_entry* base_ce, const char *isostr, size_t isostr_len, zend_long options, zend_long *recurrences) { if (!date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), recurrences, isostr, isostr_len)) { return false; @@ -5291,7 +5291,7 @@ PHP_METHOD(DatePeriod, getIterator) zend_create_internal_iterator_zval(return_value, ZEND_THIS); } -static int check_id_allowed(char *id, zend_long what) /* {{{ */ +static int check_id_allowed(const char *id, zend_long what) /* {{{ */ { if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return 1; if ((what & PHP_DATE_TIMEZONE_GROUP_AMERICA) && strncasecmp(id, "America/", 8) == 0) return 1; @@ -5697,7 +5697,7 @@ static void date_period_object_to_hash(php_period_obj *period_obj, HashTable *pr zend_hash_str_update(props, "include_end_date", sizeof("include_end_date")-1, &zv); } -static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht) /* {{{ */ +static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, const HashTable *myht) /* {{{ */ { zval *ht_entry; @@ -5860,7 +5860,7 @@ PHP_METHOD(DatePeriod, __serialize) * Common for date_period_read_property(), date_period_write_property(), and * restore_custom_dateperiod_properties functions */ -static bool date_period_is_internal_property(zend_string *name) +static bool date_period_is_internal_property(const zend_string *name) { if ( zend_string_equals_literal(name, "start") || @@ -5877,7 +5877,7 @@ static bool date_period_is_internal_property(zend_string *name) } /* }}} */ -static void restore_custom_dateperiod_properties(zval *object, HashTable *myht) +static void restore_custom_dateperiod_properties(zval *object, const HashTable *myht) { zend_string *prop_name; zval *prop_val; @@ -5916,7 +5916,7 @@ PHP_METHOD(DatePeriod, __wakeup) { zval *object = ZEND_THIS; php_period_obj *period_obj; - HashTable *myht; + const HashTable *myht; ZEND_PARSE_PARAMETERS_NONE(); diff --git a/ext/date/php_date.h b/ext/date/php_date.h index f1b7c892001a9..e45f30d0f8c2b 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -140,7 +140,7 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime); PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, bool gm); PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_t ts, bool localtime); -PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, php_date_obj *date_obj); +PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, const php_date_obj *date_obj); /* Mechanism to set new TZ database */ PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb); From 8a3dbb0401b2b9e58705e260921bc2d0cee4d146 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 13 Mar 2025 15:07:31 +0000 Subject: [PATCH 191/503] ext/date: Change return type of check_id_allowed from int to bool --- ext/date/php_date.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 913f2b032f73d..c90edb7388b6c 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5291,7 +5291,7 @@ PHP_METHOD(DatePeriod, getIterator) zend_create_internal_iterator_zval(return_value, ZEND_THIS); } -static int check_id_allowed(const char *id, zend_long what) /* {{{ */ +static bool check_id_allowed(const char *id, zend_long what) /* {{{ */ { if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return 1; if ((what & PHP_DATE_TIMEZONE_GROUP_AMERICA) && strncasecmp(id, "America/", 8) == 0) return 1; From 77c2fcf1473496a0a103c1b67190e69758361214 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 13 Mar 2025 14:52:13 +0000 Subject: [PATCH 192/503] ext/date: Remove unused parameter --- ext/date/php_date.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index c90edb7388b6c..a533552621f2a 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5030,7 +5030,7 @@ static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib return retval; } /* }}} */ -static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_entry* base_ce, const char *isostr, size_t isostr_len, zend_long options, zend_long *recurrences) +static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_entry* base_ce, const char *isostr, size_t isostr_len, zend_long *recurrences) { if (!date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), recurrences, isostr, isostr_len)) { return false; @@ -5116,7 +5116,7 @@ PHP_METHOD(DatePeriod, createFromISO8601String) dpobj->current = NULL; - if (!date_period_init_iso8601_string(dpobj, date_ce_immutable, isostr, isostr_len, options, &recurrences)) { + if (!date_period_init_iso8601_string(dpobj, date_ce_immutable, isostr, isostr_len, &recurrences)) { RETURN_THROWS(); } @@ -5155,7 +5155,7 @@ PHP_METHOD(DatePeriod, __construct) RETURN_THROWS(); } - if (!date_period_init_iso8601_string(dpobj, date_ce_date, isostr, isostr_len, options, &recurrences)) { + if (!date_period_init_iso8601_string(dpobj, date_ce_date, isostr, isostr_len, &recurrences)) { RETURN_THROWS(); } } else { From 6ff9ca12d60bc843adc4c87febc7d3b7e013b164 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 13 Mar 2025 20:11:45 +0000 Subject: [PATCH 193/503] ext/date: Pack php_interval_obj This reduces the size of the struct from 88 to 80 bytes. --- ext/date/php_date.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/date/php_date.h b/ext/date/php_date.h index e45f30d0f8c2b..f5f43bc7dfb0f 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -89,9 +89,9 @@ static inline php_timezone_obj *php_timezone_obj_from_obj(zend_object *obj) { struct _php_interval_obj { timelib_rel_time *diff; int civil_or_wall; + bool initialized; bool from_string; zend_string *date_string; - bool initialized; zend_object std; }; From a1620048fb4714ea503560406bc782e7eacfb890 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 9 Mar 2025 14:04:01 +0000 Subject: [PATCH 194/503] ext/gd: imagecrop rect argument overflow fixes. ``` ext/gd/libgd/gd.c:2275:14: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' #0 0x5d6a2103e1db in php_gd_gdImageCopy /home/dcarlier/Contribs/php-src/ext/gd/libgd/gd.c:2275 #1 0x5d6a210a2b63 in gdImageCrop /home/dcarlier/Contribs/php-src/ext/gd/libgd/gd_crop.c:57 #2 0x5d6a21018ca4 in zif_imagecrop /home/dcarlier/Contribs/php-src/ext/gd/gd.c:3575 #3 0x5d6a21e46e7a in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:1337 #4 0x5d6a221188da in execute_ex /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:57246 #5 0x5d6a221366bd in zend_execute /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:61634 #6 0x5d6a21d107a6 in zend_execute_scripts /home/dcarlier/Contribs/php-src/Zend/zend.c:1895 #7 0x5d6a21a63409 in php_execute_script /home/dcarlier/Contribs/php-src/main/main.c:2529 #8 0x5d6a22516d5e in do_cli /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:966 #9 0x5d6a2251981d in main /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:1341 #10 0x7f10d002a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #11 0x7f10d002a47a in __libc_start_main_impl ../csu/libc-start.c:360 #12 0x5d6a20a06da4 in _start (/home/dcarlier/Contribs/php-src/sapi/cli/php+0x2806da4) (BuildId: d9a79c7e0e4872311439d7313cb3a81fe04190a2) ``` close GH-18006 --- NEWS | 4 +++ ext/gd/gd.c | 20 +++++++++++++ ext/gd/tests/imagecrop_overflow.phpt | 45 ++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 ext/gd/tests/imagecrop_overflow.phpt diff --git a/NEWS b/NEWS index bee2ce0e09276..c08d732697cb3 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.21 +- GD: + . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage + in gdImageCrop(). (David Carlier) + - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 2585923edcc22..ae03b602cdc5b 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3560,6 +3560,26 @@ PHP_FUNCTION(imagecrop) RETURN_THROWS(); } + if ((rect.width > 0 && rect.x > INT_MAX - rect.width)) { + zend_argument_value_error(2, "overflow with \"x\" and \"width\" keys"); + RETURN_THROWS(); + } + + if ((rect.width < 0 && rect.x < INT_MIN - rect.width)) { + zend_argument_value_error(2, "underflow with \"x\" and \"width\" keys"); + RETURN_THROWS(); + } + + if ((rect.height > 0 && rect.y > INT_MAX - rect.height)) { + zend_argument_value_error(2, "overflow with \"y\" and \"height\" keys"); + RETURN_THROWS(); + } + + if ((rect.height < 0 && rect.y < INT_MIN - rect.height)) { + zend_argument_value_error(2, "underflow with \"y\" and \"height\" keys"); + RETURN_THROWS(); + } + im_crop = gdImageCrop(im, &rect); if (im_crop == NULL) { diff --git a/ext/gd/tests/imagecrop_overflow.phpt b/ext/gd/tests/imagecrop_overflow.phpt new file mode 100644 index 0000000000000..3331a6267168a --- /dev/null +++ b/ext/gd/tests/imagecrop_overflow.phpt @@ -0,0 +1,45 @@ +--TEST-- +imagecrop() overflows when the combo x/width or y/height is over INT_MAX or under INT_MIN. +--EXTENSIONS-- +gd +--FILE-- + 2147483647, "y" => 2147483647, "width" => 10, "height" => 10]; + +try { + imagecrop($img, $arr); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +$arr = ["x" => -2147483648, "y" => 0, "width" => -10, "height" => 10]; + +try { + imagecrop($img, $arr); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +$arr = ["x" => 1, "y" => 2147483647, "width" => 10, "height" => 10]; + +try { + imagecrop($img, $arr); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +$arr = ["x" => 1, "y" => -2147483648, "width" => 10, "height" => -10]; + +try { + imagecrop($img, $arr); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECT-- +imagecrop(): Argument #2 ($rectangle) overflow with "x" and "width" keys +imagecrop(): Argument #2 ($rectangle) underflow with "x" and "width" keys +imagecrop(): Argument #2 ($rectangle) overflow with "y" and "height" keys +imagecrop(): Argument #2 ($rectangle) underflow with "y" and "height" keys From fca36515b915d1a933792c0dca3b8d23c2a7ccca Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 26 Mar 2025 23:29:47 +0100 Subject: [PATCH 195/503] Improve performance of array_map() The refcounting and destruction is not necessary because zend_call_function will make a copy anyway. And zend_call_function only returns FAILURE if EG(active) is false in which case array_map shouldn't have been called in the first place. --- ext/standard/array.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index d26e238180262..89b775dc2f82f 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6749,8 +6749,6 @@ PHP_FUNCTION(array_map) if (n_arrays == 1) { zend_ulong num_key; zend_string *str_key; - zval *zv, arg; - int ret; if (Z_TYPE(arrays[0]) != IS_ARRAY) { zend_argument_type_error(2, "must be of type array, %s given", zend_zval_value_name(&arrays[0])); @@ -6767,15 +6765,14 @@ PHP_FUNCTION(array_map) array_init_size(return_value, maxlen); zend_hash_real_init(Z_ARRVAL_P(return_value), HT_IS_PACKED(Z_ARRVAL(arrays[0]))); - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, zv) { - fci.retval = &result; - fci.param_count = 1; - fci.params = &arg; + fci.retval = &result; + fci.param_count = 1; - ZVAL_COPY(&arg, zv); - ret = zend_call_function(&fci, &fci_cache); - i_zval_ptr_dtor(&arg); - if (ret != SUCCESS || Z_TYPE(result) == IS_UNDEF) { + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, fci.params) { + zend_result ret = zend_call_function(&fci, &fci_cache); + ZEND_ASSERT(ret == SUCCESS); + ZEND_IGNORE_VALUE(ret); + if (Z_TYPE(result) == IS_UNDEF) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_NULL(); } @@ -6885,7 +6882,11 @@ PHP_FUNCTION(array_map) fci.param_count = n_arrays; fci.params = params; - if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) { + zend_result ret = zend_call_function(&fci, &fci_cache); + ZEND_ASSERT(ret == SUCCESS); + ZEND_IGNORE_VALUE(ret); + + if (Z_TYPE(result) == IS_UNDEF) { efree(array_pos); zend_array_destroy(Z_ARR_P(return_value)); for (i = 0; i < n_arrays; i++) { From b6becada177e2c8598bbff6eed0a1e6cc0b861e9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 27 Mar 2025 21:51:56 +0100 Subject: [PATCH 196/503] Implement packed fast-path for array_map() --- ext/standard/array.c | 74 +++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 89b775dc2f82f..560170126646e 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6747,14 +6747,12 @@ PHP_FUNCTION(array_map) ZEND_PARSE_PARAMETERS_END(); if (n_arrays == 1) { - zend_ulong num_key; - zend_string *str_key; - if (Z_TYPE(arrays[0]) != IS_ARRAY) { zend_argument_type_error(2, "must be of type array, %s given", zend_zval_value_name(&arrays[0])); RETURN_THROWS(); } - maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0])); + const HashTable *input = Z_ARRVAL(arrays[0]); + maxlen = zend_hash_num_elements(input); /* Short-circuit: if no callback and only one array, just return it. */ if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) { @@ -6762,26 +6760,60 @@ PHP_FUNCTION(array_map) return; } - array_init_size(return_value, maxlen); - zend_hash_real_init(Z_ARRVAL_P(return_value), HT_IS_PACKED(Z_ARRVAL(arrays[0]))); - fci.retval = &result; fci.param_count = 1; - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, fci.params) { - zend_result ret = zend_call_function(&fci, &fci_cache); - ZEND_ASSERT(ret == SUCCESS); - ZEND_IGNORE_VALUE(ret); - if (Z_TYPE(result) == IS_UNDEF) { - zend_array_destroy(Z_ARR_P(return_value)); - RETURN_NULL(); - } - if (str_key) { - _zend_hash_append(Z_ARRVAL_P(return_value), str_key, &result); - } else { - zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result); - } - } ZEND_HASH_FOREACH_END(); + if (HT_IS_PACKED(input)) { + array_init_size(return_value, input->nNumUsed); + HashTable *output = Z_ARRVAL_P(return_value); + zend_hash_real_init_packed(output); + + uint32_t undefs = 0; + ZEND_HASH_FILL_PACKED(output) { + /* Can't use ZEND_HASH_PACKED_FOREACH_VAL() because we need to also account for the UNDEF values + * so the keys in the output array will match those of the input array. */ + for (zval *cur = input->arPacked, *end = input->arPacked + input->nNumUsed; cur != end; cur++) { + if (EXPECTED(!Z_ISUNDEF_P(cur))) { + fci.params = cur; + zend_result ret = zend_call_function(&fci, &fci_cache); + ZEND_ASSERT(ret == SUCCESS); + ZEND_IGNORE_VALUE(ret); + if (UNEXPECTED(Z_ISUNDEF(result))) { + ZEND_HASH_FILL_FINISH(); + zend_array_destroy(output); + RETURN_NULL(); + } + } else { + ZVAL_UNDEF(&result); + undefs++; + } + ZEND_HASH_FILL_ADD(&result); + } + } ZEND_HASH_FILL_END(); + output->nNumOfElements -= undefs; + } else { + zend_ulong num_key; + zend_string *str_key; + + array_init_size(return_value, maxlen); + HashTable *output = Z_ARRVAL_P(return_value); + zend_hash_real_init_mixed(output); + + ZEND_HASH_MAP_FOREACH_KEY_VAL(input, num_key, str_key, fci.params) { + zend_result ret = zend_call_function(&fci, &fci_cache); + ZEND_ASSERT(ret == SUCCESS); + ZEND_IGNORE_VALUE(ret); + if (UNEXPECTED(Z_ISUNDEF(result))) { + zend_array_destroy(output); + RETURN_NULL(); + } + if (str_key) { + _zend_hash_append(output, str_key, &result); + } else { + zend_hash_index_add_new(output, num_key, &result); + } + } ZEND_HASH_FOREACH_END(); + } } else { uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition)); From a5196bf3d66e138e48544e66bf26e55e6b49e749 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 28 Mar 2025 18:24:45 +0000 Subject: [PATCH 197/503] ext/pdo_pgsql: updating copy from according to pgsql extension workflow. (#18175) mainly using zend_string instead. --- ext/pdo_pgsql/pgsql_driver.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index dd3b9535a1626..4895463db4b08 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -619,27 +619,29 @@ static bool pgsql_handle_rollback(pdo_dbh_t *dbh) static bool _pdo_pgsql_send_copy_data(pdo_pgsql_db_handle *H, zval *line) { size_t query_len; - char *query; + zend_string *query; if (!try_convert_to_string(line)) { return false; } query_len = Z_STRLEN_P(line); - query = emalloc(query_len + 2); /* room for \n\0 */ - memcpy(query, Z_STRVAL_P(line), query_len); + query = zend_string_alloc(query_len + 2, false); /* room for \n\0 */ + memcpy(ZSTR_VAL(query), Z_STRVAL_P(line), query_len + 1); + ZSTR_LEN(query) = query_len; - if (query[query_len - 1] != '\n') { - query[query_len++] = '\n'; + if (query_len > 0 && ZSTR_VAL(query)[query_len - 1] != '\n') { + ZSTR_VAL(query)[query_len] = '\n'; + ZSTR_VAL(query)[query_len + 1] = '\0'; + ZSTR_LEN(query) ++; } - query[query_len] = '\0'; - if (PQputCopyData(H->server, query, query_len) != 1) { - efree(query); + if (PQputCopyData(H->server, ZSTR_VAL(query), ZSTR_LEN(query)) != 1) { + zend_string_release_ex(query, false); return false; } - efree(query); + zend_string_release_ex(query, false); return true; } From 8a713c1e90f3af967e1acee7aa09039077f53fea Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 06:13:44 +0000 Subject: [PATCH 198/503] ext/exif: Voidify exif_file_sections_free() This always returned true, and the return value was never checked anyway --- ext/exif/exif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 859324b1b96f5..74f0ed6f0d0d6 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -2157,7 +2157,7 @@ static int exif_file_sections_realloc(image_info_type *ImageInfo, int section_in /* {{{ exif_file_section_free Discard all file_sections in ImageInfo */ -static bool exif_file_sections_free(image_info_type *ImageInfo) +static void exif_file_sections_free(image_info_type *ImageInfo) { int i; @@ -2168,7 +2168,6 @@ static bool exif_file_sections_free(image_info_type *ImageInfo) } EFREE_IF(ImageInfo->file.list); ImageInfo->file.count = 0; - return true; } /* }}} */ From fbc84dd0565163cc207360ae5bfec23a8af10335 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 05:33:22 +0000 Subject: [PATCH 199/503] ext/exif: Voidify exif_discard_imageinfo() This always returned true, and the return value was never checked anyway --- ext/exif/exif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 74f0ed6f0d0d6..55ebf1e97d554 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -4348,7 +4348,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo) /* {{{ exif_discard_imageinfo Discard data scanned by exif_read_file. */ -static bool exif_discard_imageinfo(image_info_type *ImageInfo) +static void exif_discard_imageinfo(image_info_type *ImageInfo) { int i; @@ -4376,7 +4376,6 @@ static bool exif_discard_imageinfo(image_info_type *ImageInfo) } exif_file_sections_free(ImageInfo); memset(ImageInfo, 0, sizeof(*ImageInfo)); - return true; } /* }}} */ From a04a5dbfb16f4bd8a48c351f6bb2affb13509b1b Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 05:42:37 +0000 Subject: [PATCH 200/503] ext/exif: Use zend_str_has_nul_byte() API --- ext/exif/exif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 55ebf1e97d554..e0b42db404c73 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -4552,7 +4552,7 @@ PHP_FUNCTION(exif_read_data) RETURN_THROWS(); } - if (CHECK_NULL_PATH(Z_STRVAL_P(stream), Z_STRLEN_P(stream))) { + if (UNEXPECTED(zend_str_has_nul_byte(Z_STR_P(stream)))) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } From 96d41a67c5599558441e3b154fcfc0f1f520a5a8 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 04:48:11 +0000 Subject: [PATCH 201/503] ext/exif: Remove useless char* cast --- ext/exif/exif.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index e0b42db404c73..a3dcc6f7a69c8 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -3042,7 +3042,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP if (ByteCount>=8) { const zend_encoding *from, *to; if (!memcmp(szValuePtr, "UNICODE\0", 8)) { - *pszEncoding = estrdup((const char*)szValuePtr); + *pszEncoding = estrdup(szValuePtr); szValuePtr = szValuePtr+8; ByteCount -= 8; /* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16) @@ -3075,12 +3075,12 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP } return len; } else if (!memcmp(szValuePtr, "ASCII\0\0\0", 8)) { - *pszEncoding = estrdup((const char*)szValuePtr); + *pszEncoding = estrdup(szValuePtr); szValuePtr = szValuePtr+8; ByteCount -= 8; } else if (!memcmp(szValuePtr, "JIS\0\0\0\0\0", 8)) { /* JIS should be translated to MB or we leave it to the user - leave it to the user */ - *pszEncoding = estrdup((const char*)szValuePtr); + *pszEncoding = estrdup(szValuePtr); szValuePtr = szValuePtr+8; ByteCount -= 8; /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */ @@ -4588,7 +4588,7 @@ PHP_FUNCTION(exif_read_data) exif_iif_add_int(&ImageInfo, SECTION_FILE, "FileDateTime", ImageInfo.FileDateTime); exif_iif_add_int(&ImageInfo, SECTION_FILE, "FileSize", ImageInfo.FileSize); exif_iif_add_int(&ImageInfo, SECTION_FILE, "FileType", ImageInfo.FileType); - exif_iif_add_str(&ImageInfo, SECTION_FILE, "MimeType", (char*)php_image_type_to_mime_type(ImageInfo.FileType)); + exif_iif_add_str(&ImageInfo, SECTION_FILE, "MimeType", php_image_type_to_mime_type(ImageInfo.FileType)); exif_iif_add_str(&ImageInfo, SECTION_FILE, "SectionsFound", sections_str ? sections_str : "NONE"); #ifdef EXIF_DEBUG From 64569d3b8afe194bedd9369ecc91c085b7c34ba6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 04:32:26 +0000 Subject: [PATCH 202/503] ext/exif: Add some const qualifiers --- ext/exif/exif.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index a3dcc6f7a69c8..ba30a16fbc6ce 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -1833,7 +1833,7 @@ typedef struct { #define FOUND_WINXP (1<= and <= to do the checks, respectively. */ - end = start + length; + const char *end = start + length; return start >= info->valid_start && end <= info->valid_end; } @@ -2184,7 +2183,7 @@ static image_info_data *exif_alloc_image_info_data(image_info_list *info_list) { /* {{{ exif_iif_add_value Add a value to image_info */ -static void exif_iif_add_value(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value, size_t value_len, int motorola_intel) +static void exif_iif_add_value(image_info_type *image_info, int section_index, const char *name, int tag, int format, size_t length, void* value, size_t value_len, int motorola_intel) { size_t idex; void *vptr, *vptr_end; @@ -2323,7 +2322,7 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c /* {{{ exif_iif_add_tag Add a tag from IFD to image_info */ -static void exif_iif_add_tag(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value, size_t value_len) +static void exif_iif_add_tag(image_info_type *image_info, int section_index, const char *name, int tag, int format, size_t length, void* value, size_t value_len) { exif_iif_add_value(image_info, section_index, name, tag, format, length, value, value_len, image_info->motorola_intel); } @@ -2332,7 +2331,7 @@ static void exif_iif_add_tag(image_info_type *image_info, int section_index, cha /* {{{ exif_iif_add_int Add an int value to image_info */ -static void exif_iif_add_int(image_info_type *image_info, int section_index, char *name, int value) +static void exif_iif_add_int(image_info_type *image_info, int section_index, const char *name, int value) { image_info_data *info_data = exif_alloc_image_info_data(&image_info->info_list[section_index]); info_data->tag = TAG_NONE; @@ -2347,7 +2346,7 @@ static void exif_iif_add_int(image_info_type *image_info, int section_index, cha /* {{{ exif_iif_add_str Add a string value to image_info MUST BE NUL TERMINATED */ -static void exif_iif_add_str(image_info_type *image_info, int section_index, char *name, char *value) +static void exif_iif_add_str(image_info_type *image_info, int section_index, const char *name, const char *value) { if (value) { image_info_data *info_data = @@ -2365,7 +2364,7 @@ static void exif_iif_add_str(image_info_type *image_info, int section_index, cha /* {{{ exif_iif_add_fmt Add a format string value to image_info MUST BE NUL TERMINATED */ -static void exif_iif_add_fmt(image_info_type *image_info, int section_index, char *name, char *value, ...) +static void exif_iif_add_fmt(image_info_type *image_info, int section_index, const char *name, char *value, ...) { char *tmp; va_list arglist; @@ -2383,7 +2382,7 @@ static void exif_iif_add_fmt(image_info_type *image_info, int section_index, cha /* {{{ exif_iif_add_str Add a string value to image_info MUST BE NUL TERMINATED */ -static void exif_iif_add_buffer(image_info_type *image_info, int section_index, char *name, int length, char *value) +static void exif_iif_add_buffer(image_info_type *image_info, int section_index, const char *name, int length, const char *value) { if (value) { image_info_data *info_data = @@ -2979,7 +2978,7 @@ static void exif_thumbnail_extract(image_info_type *ImageInfo, const exif_offset /* {{{ exif_process_undefined * Copy a string/buffer in Exif header to a character string and return length of allocated buffer if any. */ -static int exif_process_undefined(char **result, char *value, size_t byte_count) { +static int exif_process_undefined(char **result, const char *value, size_t byte_count) { /* we cannot use strlcpy - here the problem is that we have to copy NUL * chars up to byte_count, we also have to add a single NUL character to * force end of string. @@ -2995,7 +2994,7 @@ static int exif_process_undefined(char **result, char *value, size_t byte_count) /* {{{ exif_process_string_raw * Copy a string in Exif header to a character string returns length of allocated buffer if any. */ -static int exif_process_string_raw(char **result, char *value, size_t byte_count) { +static int exif_process_string_raw(char **result, const char *value, size_t byte_count) { /* we cannot use strlcpy - here the problem is that we have to copy NUL * chars up to byte_count, we also have to add a single NUL character to * force end of string. @@ -3013,7 +3012,7 @@ static int exif_process_string_raw(char **result, char *value, size_t byte_count /* {{{ exif_process_string * Copy a string in Exif header to a character string and return length of allocated buffer if any. * In contrast to exif_process_string this function does always return a string buffer */ -static int exif_process_string(char **result, char *value, size_t byte_count) { +static int exif_process_string(char **result, const char *value, size_t byte_count) { /* we cannot use strlcpy - here the problem is that we cannot use strlen to * determine length of string and we cannot use strlcpy with len=byte_count+1 * because then we might get into an EXCEPTION if we exceed an allocated @@ -3031,7 +3030,7 @@ static int exif_process_string(char **result, char *value, size_t byte_count) { /* {{{ exif_process_user_comment * Process UserComment in IFD. */ -static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoPtr, char **pszEncoding, char *szValuePtr, int ByteCount) +static int exif_process_user_comment(const image_info_type *ImageInfo, char **pszInfoPtr, char **pszEncoding, char *szValuePtr, int ByteCount) { int a; char *decode; @@ -3119,7 +3118,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP /* {{{ exif_process_unicode * Process unicode field in IFD. */ -static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_field, int tag, char *szValuePtr, int ByteCount) +static int exif_process_unicode(const image_info_type *ImageInfo, xp_field_type *xp_field, int tag, const char *szValuePtr, int ByteCount) { xp_field->tag = tag; xp_field->value = NULL; @@ -3127,7 +3126,7 @@ static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_fi if (zend_multibyte_encoding_converter( (unsigned char**)&xp_field->value, &xp_field->size, - (unsigned char*)szValuePtr, + (const unsigned char*)szValuePtr, ByteCount, zend_multibyte_fetch_encoding(ImageInfo->encode_unicode), zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_unicode_be : ImageInfo->decode_unicode_le) @@ -4463,7 +4462,7 @@ static bool exif_read_from_stream(image_info_type *ImageInfo, php_stream *stream /* }}} */ /* {{{ exif_read_from_file */ -static bool exif_read_from_file(image_info_type *ImageInfo, char *FileName, int read_thumbnail, int read_all) +static bool exif_read_from_file(image_info_type *ImageInfo, const char *FileName, int read_thumbnail, int read_all) { bool ret; php_stream *stream; From aa92c70134c6aa778fe0a11275e7819e0b9243a5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 25 Mar 2025 06:13:07 +0000 Subject: [PATCH 203/503] ext/exif: Reduce scope of variable --- ext/exif/exif.c | 69 +++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index ba30a16fbc6ce..2c2546a534132 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -2158,10 +2158,8 @@ static int exif_file_sections_realloc(image_info_type *ImageInfo, int section_in */ static void exif_file_sections_free(image_info_type *ImageInfo) { - int i; - if (ImageInfo->file.count) { - for (i=0; ifile.count; i++) { + for (int i = 0; ifile.count; i++) { EFREE_IF(ImageInfo->file.list[i].data); } } @@ -2403,11 +2401,10 @@ static void exif_iif_add_buffer(image_info_type *image_info, int section_index, Free memory allocated for image_info */ static void exif_iif_free(image_info_type *image_info, int section_index) { - int i; void *f; /* faster */ if (image_info->info_list[section_index].count) { - for (i=0; i < image_info->info_list[section_index].count; i++) { + for (int i = 0; i < image_info->info_list[section_index].count; i++) { if ((f=image_info->info_list[section_index].list[i].name) != NULL) { efree(f); } @@ -2448,7 +2445,6 @@ static void exif_iif_free(image_info_type *image_info, int section_index) { * Add image_info to associative array value. */ static void add_assoc_image_info(zval *value, int sub_array, image_info_type *image_info, int section_index) { - char buffer[64], uname[64]; int idx = 0, unknown = 0; if (!image_info->info_list[section_index].count) { @@ -2466,6 +2462,8 @@ static void add_assoc_image_info(zval *value, int sub_array, image_info_type *im image_info_data *info_data = &image_info->info_list[section_index].list[i]; image_info_value *info_value = &info_data->value; const char *name = info_data->name; + char uname[64]; + if (!name) { snprintf(uname, sizeof(uname), "%d", unknown++); name = uname; @@ -2516,6 +2514,7 @@ static void add_assoc_image_info(zval *value, int sub_array, image_info_type *im array_init(&array); } for (int ap = 0; ap < l; ap++) { + char buffer[64]; if (l>1) { info_value = &info_data->value.list[ap]; } @@ -2785,8 +2784,7 @@ PHP_FUNCTION(exif_tagname) * Create a value for an ifd from an info_data pointer */ static void* exif_ifd_make_value(image_info_data *info_data, int motorola_intel) { size_t byte_count; - char *value_ptr, *data_ptr; - size_t i; + char *value_ptr; image_info_value *info_value; @@ -2808,8 +2806,8 @@ static void* exif_ifd_make_value(image_info_data *info_data, int motorola_intel) *value_ptr = info_data->value.i; return value_ptr; } else { - data_ptr = value_ptr; - for(i=0; ilength; i++) { + char *data_ptr = value_ptr; + for(size_t i = 0; i < info_data->length; i++) { if (info_data->length==1) { info_value = &info_data->value; } else { @@ -3032,8 +3030,6 @@ static int exif_process_string(char **result, const char *value, size_t byte_cou * Process UserComment in IFD. */ static int exif_process_user_comment(const image_info_type *ImageInfo, char **pszInfoPtr, char **pszEncoding, char *szValuePtr, int ByteCount) { - int a; - char *decode; size_t len; *pszEncoding = NULL; @@ -3041,6 +3037,7 @@ static int exif_process_user_comment(const image_info_type *ImageInfo, char **ps if (ByteCount>=8) { const zend_encoding *from, *to; if (!memcmp(szValuePtr, "UNICODE\0", 8)) { + char *decode; *pszEncoding = estrdup(szValuePtr); szValuePtr = szValuePtr+8; ByteCount -= 8; @@ -3105,7 +3102,7 @@ static int exif_process_user_comment(const image_info_type *ImageInfo, char **ps /* Olympus has this padded with trailing spaces. Remove these first. */ if (ByteCount>0) { - for (a=ByteCount-1;a && szValuePtr[a]==' ';a--) { + for (int a = ByteCount-1; a && szValuePtr[a]==' '; a--) { (szValuePtr)[a] = '\0'; } } @@ -3141,14 +3138,13 @@ static int exif_process_unicode(const image_info_type *ImageInfo, xp_field_type * Process nested IFDs directories in Maker Note. */ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * value_ptr, int value_len, const exif_offset_info *info, size_t displacement) { - size_t i; - int de, section_index = SECTION_MAKERNOTE; + int section_index = SECTION_MAKERNOTE; int NumDirEntries, old_motorola_intel; const maker_note_type *maker_note; char *dir_start; exif_offset_info new_info; - for (i=0; i<=sizeof(maker_note_array)/sizeof(maker_note_type); i++) { + for (size_t i = 0; i <= sizeof(maker_note_array)/sizeof(maker_note_type); i++) { if (i==sizeof(maker_note_array)/sizeof(maker_note_type)) { #ifdef EXIF_DEBUG exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "No maker note data found. Detected maker: %s (length = %d)", ImageInfo->make, ImageInfo->make ? strlen(ImageInfo->make) : 0); @@ -3229,7 +3225,7 @@ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * val break; } - for (de=0;detag_table)) { @@ -3257,16 +3253,10 @@ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * val * Process one of the nested IFDs directories. */ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entry, const exif_offset_info *info, size_t displacement, int section_index, int ReadNextIFD, tag_table_type tag_table) { - size_t length; unsigned int tag, format, components; char *value_ptr, tagname[64], cbuf[32], *outside=NULL; - size_t byte_count, offset_val, fpos, fgot; + size_t byte_count, offset_val; int64_t byte_count_signed; - xp_field_type *tmp_xp; -#ifdef EXIF_DEBUG - char *dump_data; - int dump_free; -#endif /* EXIF_DEBUG */ tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel); format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel); @@ -3314,9 +3304,9 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr value_ptr = cbuf; } - fpos = php_stream_tell(ImageInfo->infile); + size_t fpos = php_stream_tell(ImageInfo->infile); php_stream_seek(ImageInfo->infile, displacement+offset_val, SEEK_SET); - fgot = php_stream_tell(ImageInfo->infile); + size_t fgot = php_stream_tell(ImageInfo->infile); if (fgot!=displacement+offset_val) { EFREE_IF(outside); exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Wrong file pointer: 0x%08X != 0x%08X", fgot, displacement+offset_val); @@ -3339,7 +3329,8 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr ImageInfo->sections_found |= FOUND_ANY_TAG; #ifdef EXIF_DEBUG - dump_data = exif_dump_data(&dump_free, format, components, ImageInfo->motorola_intel, value_ptr); + int dump_free; + char *dump_data = exif_dump_data(&dump_free, format, components, ImageInfo->motorola_intel, value_ptr); exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Process tag(x%04X=%s,@0x%04X + x%04X(=%d)): %s%s %s", tag, exif_get_tagname_debug(tag, tag_table), offset_val+displacement, byte_count, byte_count, (components>1)&&format!=TAG_FMT_UNDEFINED&&format!=TAG_FMT_STRING?"ARRAY OF ":"", exif_get_tagformat(format), dump_data); @@ -3392,7 +3383,8 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr } else { if (section_index==SECTION_IFD0 || section_index==SECTION_EXIF) switch(tag) { - case TAG_COPYRIGHT: + case TAG_COPYRIGHT: { + size_t length; /* check for " NUL NUL" */ if (byte_count>1 && (length=zend_strnlen(value_ptr, byte_count)) > 0) { if (lengthUserComment); @@ -3425,13 +3418,14 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr case TAG_XP_COMMENTS: case TAG_XP_AUTHOR: case TAG_XP_KEYWORDS: - case TAG_XP_SUBJECT: - tmp_xp = (xp_field_type*)safe_erealloc(ImageInfo->xp_fields.list, (ImageInfo->xp_fields.count+1), sizeof(xp_field_type), 0); + case TAG_XP_SUBJECT: { + xp_field_type *tmp_xp = (xp_field_type*)safe_erealloc(ImageInfo->xp_fields.list, (ImageInfo->xp_fields.count+1), sizeof(xp_field_type), 0); ImageInfo->sections_found |= FOUND_WINXP; ImageInfo->xp_fields.list = tmp_xp; ImageInfo->xp_fields.count++; exif_process_unicode(ImageInfo, &(ImageInfo->xp_fields.list[ImageInfo->xp_fields.count-1]), tag, value_ptr, byte_count); break; + } case TAG_FNUMBER: /* Simplest way of expressing aperture, so I trust it the most. @@ -4032,7 +4026,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir { int i, sn, num_entries, sub_section_index = 0; unsigned char *dir_entry; - size_t ifd_size, dir_size, entry_offset, next_offset, entry_length, entry_value=0, fgot; + size_t ifd_size, dir_size, next_offset, entry_length, entry_value=0; int entry_tag , entry_type; tag_table_type tag_table = exif_get_tag_table(section_index); @@ -4119,7 +4113,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir break; } } else { - entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); + size_t entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); /* if entry needs expanding ifd cache and entry is at end of current ifd cache. */ /* otherwise there may be huge holes between two entries */ if (entry_offset + entry_length > dir_offset + ifd_size @@ -4178,7 +4172,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir sub_section_index = SECTION_THUMBNAIL; break; } - entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); + size_t entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); #ifdef EXIF_DEBUG exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Next IFD: %s @0x%04X", exif_get_sectionname(sub_section_index), entry_offset); #endif @@ -4195,7 +4189,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir if (!ImageInfo->Thumbnail.data) { ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0); php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET); - fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); + size_t fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); if (fgot != ImageInfo->Thumbnail.size) { EXIF_ERRLOG_THUMBEOF(ImageInfo) efree(ImageInfo->Thumbnail.data); @@ -4235,7 +4229,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir if (!ImageInfo->Thumbnail.data && ImageInfo->Thumbnail.offset && ImageInfo->Thumbnail.size && ImageInfo->read_thumbnail) { ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0); php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET); - fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); + size_t fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); if (fgot != ImageInfo->Thumbnail.size) { EXIF_ERRLOG_THUMBEOF(ImageInfo) efree(ImageInfo->Thumbnail.data); @@ -4494,7 +4488,7 @@ PHP_FUNCTION(exif_read_data) bool ret; int i, sections_needed = 0; image_info_type ImageInfo; - char tmp[64], *sections_str, *s; + char *sections_str; /* Parse arguments */ ZEND_PARSE_PARAMETERS_START(1, 4) @@ -4510,7 +4504,7 @@ PHP_FUNCTION(exif_read_data) if (z_sections_needed) { spprintf(§ions_str, 0, ",%s,", ZSTR_VAL(z_sections_needed)); /* sections_str DOES start with , and SPACES are NOT allowed in names */ - s = sections_str; + char *s = sections_str; while (*++s) { if (*s == ' ') { *s = ','; @@ -4518,6 +4512,7 @@ PHP_FUNCTION(exif_read_data) } for (i = 0; i < SECTION_COUNT; i++) { + char tmp[64]; snprintf(tmp, sizeof(tmp), ",%s,", exif_get_sectionname(i)); if (strstr(sections_str, tmp)) { sections_needed |= 1< Date: Tue, 25 Mar 2025 05:32:12 +0000 Subject: [PATCH 204/503] ext/exif: Refactor implementation of exif_scan_FILE_header() --- ext/exif/exif.c | 93 +++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 2c2546a534132..0f63c76e2323f 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -4278,63 +4278,72 @@ static bool exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offs static bool exif_scan_FILE_header(image_info_type *ImageInfo) { unsigned char file_header[8]; - bool ret = false; ImageInfo->FileType = IMAGE_FILETYPE_UNKNOWN; - if (ImageInfo->FileSize >= 2) { - php_stream_seek(ImageInfo->infile, 0, SEEK_SET); - if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)file_header, 2) != 2) { + if (UNEXPECTED(ImageInfo->FileSize < 2)) { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File too small (%d)", ImageInfo->FileSize); + return false; + } + + php_stream_seek(ImageInfo->infile, 0, SEEK_SET); + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)file_header, 2) != 2) { + return false; + } + + if ((file_header[0]==0xff) && (file_header[1]==M_SOI)) { + ImageInfo->FileType = IMAGE_FILETYPE_JPEG; + if (exif_scan_JPEG_header(ImageInfo)) { + return true; + } else { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid JPEG file"); + return false; + } + } else if (ImageInfo->FileSize >= 8) { + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(file_header+2), 6) != 6) { return false; } - if ((file_header[0]==0xff) && (file_header[1]==M_SOI)) { - ImageInfo->FileType = IMAGE_FILETYPE_JPEG; - if (exif_scan_JPEG_header(ImageInfo)) { - ret = true; + + if (!memcmp(file_header, "II\x2A\x00", 4)) { + ImageInfo->FileType = IMAGE_FILETYPE_TIFF_II; + ImageInfo->motorola_intel = 0; +#ifdef EXIF_DEBUG + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/II format"); +#endif + ImageInfo->sections_found |= FOUND_IFD0; + if (exif_process_IFD_in_TIFF( + ImageInfo, + php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel), + SECTION_IFD0 + )) { + return true; } else { - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid JPEG file"); - } - } else if (ImageInfo->FileSize >= 8) { - if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(file_header+2), 6) != 6) { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); return false; } - if (!memcmp(file_header, "II\x2A\x00", 4)) { - ImageInfo->FileType = IMAGE_FILETYPE_TIFF_II; - ImageInfo->motorola_intel = 0; -#ifdef EXIF_DEBUG - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/II format"); -#endif - ImageInfo->sections_found |= FOUND_IFD0; - if (exif_process_IFD_in_TIFF(ImageInfo, - php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel), - SECTION_IFD0)) { - ret = true; - } else { - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); - } - } else if (!memcmp(file_header, "MM\x00\x2a", 4)) { - ImageInfo->FileType = IMAGE_FILETYPE_TIFF_MM; - ImageInfo->motorola_intel = 1; + } else if (!memcmp(file_header, "MM\x00\x2a", 4)) { + ImageInfo->FileType = IMAGE_FILETYPE_TIFF_MM; + ImageInfo->motorola_intel = 1; #ifdef EXIF_DEBUG - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/MM format"); + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/MM format"); #endif - ImageInfo->sections_found |= FOUND_IFD0; - if (exif_process_IFD_in_TIFF(ImageInfo, - php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel), - SECTION_IFD0)) { - ret = true; - } else { - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); - } + ImageInfo->sections_found |= FOUND_IFD0; + if (exif_process_IFD_in_TIFF( + ImageInfo, + php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel), + SECTION_IFD0 + )) { + return true; } else { - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File not supported"); + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); return false; } + } else { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File not supported"); + return false; } - } else { - exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File too small (%d)", ImageInfo->FileSize); } - return ret; + return false; } /* }}} */ From 314219387e06ebce5fa5639ce8b6697c2553bcf8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 01:02:17 +0100 Subject: [PATCH 205/503] Improve performance of user-callbacked sort functions (#18166) --- ext/standard/array.c | 83 +++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 560170126646e..994e0ad34a8cb 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -632,6 +632,18 @@ PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */ } /* }}} */ +/* Consumes `zv` */ +static zend_always_inline zend_long php_get_long(zval *zv) +{ + if (EXPECTED(Z_TYPE_P(zv) == IS_LONG)) { + return Z_LVAL_P(zv); + } else { + zend_long ret = zval_get_long_func(zv, false); + zval_ptr_dtor(zv); + return ret; + } +} + /* {{{ Count the number of elements in a variable (usually an array) */ PHP_FUNCTION(count) { @@ -677,8 +689,7 @@ PHP_FUNCTION(count) zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); if (Z_TYPE(retval) != IS_UNDEF) { - RETVAL_LONG(zval_get_long(&retval)); - zval_ptr_dtor(&retval); + RETVAL_LONG(php_get_long(&retval)); } return; } @@ -811,20 +822,14 @@ static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s) /* {{{ * { zval args[2]; zval retval; - bool call_failed; - ZVAL_COPY(&args[0], &f->val); - ZVAL_COPY(&args[1], &s->val); + ZVAL_COPY_VALUE(&args[0], &f->val); + ZVAL_COPY_VALUE(&args[1], &s->val); BG(user_compare_fci).param_count = 2; BG(user_compare_fci).params = args; BG(user_compare_fci).retval = &retval; - call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF; - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - if (UNEXPECTED(call_failed)) { - return 0; - } + zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)); if (UNEXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { if (!ARRAYG(compare_deprecation_thrown)) { @@ -836,23 +841,16 @@ static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s) /* {{{ * if (Z_TYPE(retval) == IS_FALSE) { /* Retry with swapped operands. */ - ZVAL_COPY(&args[0], &s->val); - ZVAL_COPY(&args[1], &f->val); - call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF; - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - if (call_failed) { - return 0; - } + ZVAL_COPY_VALUE(&args[0], &s->val); + ZVAL_COPY_VALUE(&args[1], &f->val); + zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)); - zend_long ret = zval_get_long(&retval); - zval_ptr_dtor(&retval); + zend_long ret = php_get_long(&retval); return -ZEND_NORMALIZE_BOOL(ret); } } - zend_long ret = zval_get_long(&retval); - zval_ptr_dtor(&retval); + zend_long ret = php_get_long(&retval); return ZEND_NORMALIZE_BOOL(ret); } /* }}} */ @@ -929,28 +927,22 @@ static inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s) /* { { zval args[2]; zval retval; - bool call_failed; if (f->key == NULL) { ZVAL_LONG(&args[0], f->h); } else { - ZVAL_STR_COPY(&args[0], f->key); + ZVAL_STR(&args[0], f->key); } if (s->key == NULL) { ZVAL_LONG(&args[1], s->h); } else { - ZVAL_STR_COPY(&args[1], s->key); + ZVAL_STR(&args[1], s->key); } BG(user_compare_fci).param_count = 2; BG(user_compare_fci).params = args; BG(user_compare_fci).retval = &retval; - call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF; - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - if (UNEXPECTED(call_failed)) { - return 0; - } + zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)); if (UNEXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { if (!ARRAYG(compare_deprecation_thrown)) { @@ -965,29 +957,22 @@ static inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s) /* { if (s->key == NULL) { ZVAL_LONG(&args[0], s->h); } else { - ZVAL_STR_COPY(&args[0], s->key); + ZVAL_STR(&args[0], s->key); } if (f->key == NULL) { ZVAL_LONG(&args[1], f->h); } else { - ZVAL_STR_COPY(&args[1], f->key); + ZVAL_STR(&args[1], f->key); } - call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF; - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - if (call_failed) { - return 0; - } + zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)); - zend_long ret = zval_get_long(&retval); - zval_ptr_dtor(&retval); + zend_long ret = php_get_long(&retval); return -ZEND_NORMALIZE_BOOL(ret); } } - zend_long result = zval_get_long(&retval); - zval_ptr_dtor(&retval); + zend_long result = php_get_long(&retval); return ZEND_NORMALIZE_BOOL(result); } /* }}} */ @@ -5065,13 +5050,9 @@ static int zval_user_compare(zval *a, zval *b) /* {{{ */ BG(user_compare_fci).params = args; BG(user_compare_fci).retval = &retval; - if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - zend_long ret = zval_get_long(&retval); - zval_ptr_dtor(&retval); - return ZEND_NORMALIZE_BOOL(ret); - } else { - return 0; - } + zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)); + zend_long ret = php_get_long(&retval); + return ZEND_NORMALIZE_BOOL(ret); } /* }}} */ From 5dd9b0dcef229c55f67044537b076c6e4320f28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 29 Mar 2025 13:29:40 +0100 Subject: [PATCH 206/503] Add `php_build_provider()` (#18168) * Add `ZEND_ATTRIBUTE_CONST` to php_version() and php_version_id() * Add `php_build_provider()` * Use `php_build_provider()` internally --- UPGRADING.INTERNALS | 2 ++ ext/standard/info.c | 6 +++--- main/main.c | 36 +++++++++++++++++++++++------------- main/php_main.h | 11 +++++++++-- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 13b5e6a394434..eb5ccd7bd0bd0 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -23,6 +23,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES for fake closures. . Added smart_string_append_printf() matching smart_str_append_printf() for char* instead of zend_string*-based smart strings. + . Added php_build_provider() to retrieve the value of PHP_BUILD_PROVIDER at + runtime. ======================== 2. Build system changes diff --git a/ext/standard/info.c b/ext/standard/info.c index 0211265f954a9..952f0f92fe6e2 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -805,9 +805,9 @@ PHPAPI ZEND_COLD void php_print_info(int flag) #ifdef PHP_BUILD_SYSTEM php_info_print_table_row(2, "Build System", PHP_BUILD_SYSTEM); #endif -#ifdef PHP_BUILD_PROVIDER - php_info_print_table_row(2, "Build Provider", PHP_BUILD_PROVIDER); -#endif + if (php_build_provider()) { + php_info_print_table_row(2, "Build Provider", php_build_provider()); + } #ifdef PHP_BUILD_COMPILER php_info_print_table_row(2, "Compiler", PHP_BUILD_COMPILER); #endif diff --git a/main/main.c b/main/main.c index 415cb02185e94..50894939782a0 100644 --- a/main/main.c +++ b/main/main.c @@ -74,6 +74,7 @@ #include "zend_dtrace.h" #include "zend_observer.h" #include "zend_system_id.h" +#include "zend_smart_string.h" #include "php_content_types.h" #include "php_ticks.h" @@ -99,20 +100,30 @@ PHPAPI size_t core_globals_offset; const char php_build_date[] = __DATE__ " " __TIME__; -PHPAPI const char *php_version(void) +ZEND_ATTRIBUTE_CONST PHPAPI const char *php_version(void) { return PHP_VERSION; } -PHPAPI unsigned int php_version_id(void) +ZEND_ATTRIBUTE_CONST PHPAPI unsigned int php_version_id(void) { return PHP_VERSION_ID; } +ZEND_ATTRIBUTE_CONST PHPAPI const char *php_build_provider(void) +{ +#ifdef PHP_BUILD_PROVIDER + return PHP_BUILD_PROVIDER; +#else + return NULL; +#endif +} + PHPAPI char *php_get_version(sapi_module_struct *sapi_module) { - char *version_info; - spprintf(&version_info, 0, "PHP %s (%s) (built: %s) (%s)\nCopyright (c) The PHP Group\n%s%s", + smart_string version_info = {0}; + smart_string_append_printf(&version_info, + "PHP %s (%s) (built: %s) (%s)\n", PHP_VERSION, sapi_module->name, php_build_date, #ifdef ZTS "ZTS" @@ -131,16 +142,15 @@ PHPAPI char *php_get_version(sapi_module_struct *sapi_module) #ifdef HAVE_GCOV " GCOV" #endif - , -#ifdef PHP_BUILD_PROVIDER - "Built by " PHP_BUILD_PROVIDER "\n" -#else - "" -#endif - , - get_zend_version() ); - return version_info; + smart_string_appends(&version_info, "Copyright (c) The PHP Group\n"); + if (php_build_provider()) { + smart_string_append_printf(&version_info, "Built by %s\n", php_build_provider()); + } + smart_string_appends(&version_info, get_zend_version()); + smart_string_0(&version_info); + + return version_info.c; } PHPAPI void php_print_version(sapi_module_struct *sapi_module) diff --git a/main/php_main.h b/main/php_main.h index 889fcf48501f0..a5b049487db23 100644 --- a/main/php_main.h +++ b/main/php_main.h @@ -28,13 +28,20 @@ BEGIN_EXTERN_C() * extensions which want to know the version of PHP at run-time, rather than * the version they were built with at compile-time. */ -PHPAPI const char *php_version(void); +ZEND_ATTRIBUTE_CONST PHPAPI const char *php_version(void); /* Returns the PHP version id the engine was built with. This is useful for * extensions which want to know the version of PHP at run-time, rather than * the version they were built with at compile-time. */ -PHPAPI unsigned int php_version_id(void); +ZEND_ATTRIBUTE_CONST PHPAPI unsigned int php_version_id(void); + +/* Returns the build provider specified at build time. NULL is returned if + * no build provider was specified. This is useful for extensions which want + * to know the origin of a PHP binary at run-time, for example to provide + * statistics. + */ +ZEND_ATTRIBUTE_CONST PHPAPI const char *php_build_provider(void); /* Prints the PHP version string for the -v option. It's in main/ so that * it can be shared between SAPIs. From 73c2e3cadcc9d5e25586756604dbac7f4210706f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 22:45:57 +0100 Subject: [PATCH 207/503] Avoid pointless refcounting in array_reduce (#18180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For this script: ```php for ($i=0;$i < 100; $i++) array_reduce(range(1, 100000), fn ($a,$b)=>$a+$b,1); ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php reduce_bench.php Time (mean ± σ): 272.0 ms ± 3.7 ms [User: 268.9 ms, System: 2.1 ms] Range (min … max): 268.9 ms … 281.3 ms 11 runs Benchmark 2: ./sapi/cli/php_old reduce_bench.php Time (mean ± σ): 288.2 ms ± 3.5 ms [User: 284.5 ms, System: 2.7 ms] Range (min … max): 285.0 ms … 295.9 ms 10 runs Summary ./sapi/cli/php reduce_bench.php ran 1.06 ± 0.02 times faster than ./sapi/cli/php_old reduce_bench.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php test.php Time (mean ± σ): 189.6 ms ± 3.5 ms [User: 178.5 ms, System: 10.7 ms] Range (min … max): 187.3 ms … 201.6 ms 15 runs Benchmark 2: ./sapi/cli/php_old test.php Time (mean ± σ): 204.2 ms ± 2.9 ms [User: 190.1 ms, System: 13.6 ms] Range (min … max): 200.6 ms … 210.2 ms 14 runs Summary ./sapi/cli/php test.php ran 1.08 ± 0.02 times faster than ./sapi/cli/php_old test.php ``` --- ext/standard/array.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 994e0ad34a8cb..aeaef847dd676 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6437,7 +6437,6 @@ PHP_FUNCTION(array_reduce) zval *input; zval args[2]; zval *operand; - zval retval; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; zval *initial = NULL; @@ -6450,8 +6449,7 @@ PHP_FUNCTION(array_reduce) Z_PARAM_ZVAL(initial) ZEND_PARSE_PARAMETERS_END(); - - if (ZEND_NUM_ARGS() > 2) { + if (initial) { ZVAL_COPY(return_value, initial); } else { ZVAL_NULL(return_value); @@ -6466,24 +6464,22 @@ PHP_FUNCTION(array_reduce) return; } - fci.retval = &retval; + fci.retval = return_value; fci.param_count = 2; + fci.params = args; ZEND_HASH_FOREACH_VAL(htbl, operand) { ZVAL_COPY_VALUE(&args[0], return_value); - ZVAL_COPY(&args[1], operand); - fci.params = args; + ZVAL_COPY_VALUE(&args[1], operand); - if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - ZVAL_COPY_VALUE(return_value, &retval); + zend_call_function(&fci, &fci_cache); + zval_ptr_dtor(&args[0]); + + if (EXPECTED(!Z_ISUNDEF_P(return_value))) { if (UNEXPECTED(Z_ISREF_P(return_value))) { zend_unwrap_reference(return_value); } } else { - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); RETURN_NULL(); } } ZEND_HASH_FOREACH_END(); From d456d25a1c27bafc8a1e2757d1e5215e38163ca4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 22:46:08 +0100 Subject: [PATCH 208/503] Get rid of temporary in array_push (#18181) This only makes a very very small improvement in performance, but the code size on x86-64 decreases from 357 bytes to 296 bytes. --- ext/standard/array.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index aeaef847dd676..adb2a20d60388 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3502,8 +3502,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H PHP_FUNCTION(array_push) { zval *args, /* Function arguments array */ - *stack, /* Input array */ - new_var; /* Variable to be pushed */ + *stack; /* Input array */ uint32_t argc; /* Number of function arguments */ @@ -3514,10 +3513,10 @@ PHP_FUNCTION(array_push) /* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */ for (uint32_t i = 0; i < argc; i++) { - ZVAL_COPY(&new_var, &args[i]); + Z_TRY_ADDREF(args[i]); - if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) { - Z_TRY_DELREF(new_var); + if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &args[i]) == NULL) { + Z_TRY_DELREF(args[i]); zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); RETURN_THROWS(); } From 0733e453c791ebc8e46a4294a01fc89cbf35ec01 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 22:46:18 +0100 Subject: [PATCH 209/503] Remove useless operations in namespace_compat (#18182) We never use the return value, so we can avoid a double lookup and a return. --- ext/dom/namespace_compat.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/ext/dom/namespace_compat.c b/ext/dom/namespace_compat.c index 7a3bd68b0111a..ee32ec39dbeb3 100644 --- a/ext/dom/namespace_compat.c +++ b/ext/dom/namespace_compat.c @@ -180,7 +180,7 @@ PHP_DOM_EXPORT xmlNsPtr php_dom_libxml_ns_mapper_get_ns_raw_strings_nullsafe(php return php_dom_libxml_ns_mapper_get_ns_raw_strings(mapper, prefix, uri); } -static xmlNsPtr php_dom_libxml_ns_mapper_store_and_normalize_parsed_ns(php_dom_libxml_ns_mapper *mapper, xmlNsPtr ns) +static void php_dom_libxml_ns_mapper_store_and_normalize_parsed_ns(php_dom_libxml_ns_mapper *mapper, xmlNsPtr ns) { ZEND_ASSERT(ns != NULL); @@ -198,16 +198,9 @@ static xmlNsPtr php_dom_libxml_ns_mapper_store_and_normalize_parsed_ns(php_dom_l prefix_len = xmlStrlen(ns->prefix); } - zval *zv = zend_hash_str_find_ptr(prefix_map, prefix, prefix_len); - if (zv != NULL) { - return Z_PTR_P(zv); - } - zval new_zv; DOM_Z_UNOWNED(&new_zv, ns); - zend_hash_str_add_new(prefix_map, prefix, prefix_len, &new_zv); - - return ns; + zend_hash_str_add(prefix_map, prefix, prefix_len, &new_zv); } typedef struct { From c0b441f8fde516e714586d85603d8a25aea1d4e8 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 30 Mar 2025 00:42:59 +0100 Subject: [PATCH 210/503] [skip ci] Fix valgrind benchmark diff output Don't print command when searching benchmarked commit, as this breaks the markdown summary. --- benchmark/generate_diff.php | 6 +++++- benchmark/shared.php | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/benchmark/generate_diff.php b/benchmark/generate_diff.php index 3a1e0d7b1370f..94c020df4b998 100644 --- a/benchmark/generate_diff.php +++ b/benchmark/generate_diff.php @@ -73,7 +73,11 @@ function find_benchmarked_commit_hash(string $repo, string $commitHash): ?string if (file_exists($summaryFile)) { break; } - $commitHash = trim(runCommand(['git', 'rev-parse', $commitHash . '^'], dirname(__DIR__))->stdout); + $commitHash = trim(runCommand( + ['git', 'rev-parse', $commitHash . '^'], + dirname(__DIR__), + printCommand: false, + )->stdout); } return $commitHash; diff --git a/benchmark/shared.php b/benchmark/shared.php index 450101770b28b..0f58a2a1bf870 100644 --- a/benchmark/shared.php +++ b/benchmark/shared.php @@ -5,12 +5,14 @@ class ProcessResult { public $stderr; } -function runCommand(array $args, ?string $cwd = null): ProcessResult { +function runCommand(array $args, ?string $cwd = null, bool $printCommand = true): ProcessResult { $cmd = implode(' ', array_map('escapeshellarg', $args)); $pipes = null; $result = new ProcessResult(); $descriptorSpec = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; - fwrite(STDOUT, "> $cmd\n"); + if ($printCommand) { + fwrite(STDOUT, "> $cmd\n"); + } $processHandle = proc_open($cmd, $descriptorSpec, $pipes, $cwd ?? getcwd(), null); $stdin = $pipes[0]; From 4a7332f4c6a21ee5cc0f49ab52e521b046f239e8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 11:18:15 +0200 Subject: [PATCH 211/503] Remove pointless operations from zend_user_serialize() (#18188) We don't have to call zval_ptr_dtor() on IS_NULL, and we only have to check for the UNDEF type. Reduces code size from 231 to 199 on x86-64. --- Zend/zend_interfaces.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index c0127feabbf68..ce9cc00fdfb95 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -412,13 +412,12 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *b zend_call_method_with_0_params( Z_OBJ_P(object), Z_OBJCE_P(object), NULL, "serialize", &retval); - if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) { + if (Z_TYPE(retval) == IS_UNDEF) { result = FAILURE; } else { switch(Z_TYPE(retval)) { case IS_NULL: /* we could also make this '*buf_len = 0' but this allows to skip variables */ - zval_ptr_dtor(&retval); return FAILURE; case IS_STRING: *buffer = (unsigned char*)estrndup(Z_STRVAL(retval), Z_STRLEN(retval)); From 6e0b60cc8f992c83b760f01589a5abf71292f5f1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 13:00:09 +0200 Subject: [PATCH 212/503] Remove pointless ZVAL_UNDEF() in isset path (#18187) This will already be set to UNDEF by zend_call_function. --- Zend/zend_object_handlers.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index b21d4db5abf69..076d2b8bbc2dd 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -877,7 +877,6 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int if (!((*guard) & IN_ISSET)) { GC_ADDREF(zobj); - ZVAL_UNDEF(&tmp_result); *guard |= IN_ISSET; zend_std_call_issetter(zobj, name, &tmp_result); From 335c0b39a24c83e4d7c6ea028123d5927e900c63 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 13:16:33 +0200 Subject: [PATCH 213/503] Optimize SplFixedArray dimension performance (#18184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch optimizes reading and writing from SplFixedArray with the dimension operators. It accomplishes this due to the following optimizations: * Fast-path for long keys (inlined). * Optimization hints (UNEXPECTED + assertion) * Using an unsigned index so we can do a single length comparison For the following script: ```php $test = new SplFixedArray(4); for ($i = 0 ; $i< 5000000; $i++) $test[1] += $i; ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 95.4 ms ± 1.6 ms [User: 91.5 ms, System: 3.2 ms] Range (min … max): 93.7 ms … 100.8 ms 31 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 119.1 ms ± 1.3 ms [User: 114.7 ms, System: 3.6 ms] Range (min … max): 117.6 ms … 123.1 ms 24 runs Summary ./sapi/cli/php x.php ran 1.25 ± 0.03 times faster than ./sapi/cli/php_old x.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 67.9 ms ± 1.1 ms [User: 64.8 ms, System: 3.2 ms] Range (min … max): 66.6 ms … 72.8 ms 43 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 84.8 ms ± 1.1 ms [User: 81.0 ms, System: 3.9 ms] Range (min … max): 82.6 ms … 88.0 ms 34 runs Summary ./sapi/cli/php x.php ran 1.25 ± 0.03 times faster than ./sapi/cli/php_old x.php ``` --- ext/spl/spl_fixedarray.c | 52 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index b919501c0dd25..fa846e48eee03 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -324,14 +324,14 @@ static zend_object *spl_fixedarray_object_clone(zend_object *old_object) return new_object; } -static zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */ +static zend_never_inline zend_ulong spl_offset_convert_to_ulong_slow(const zval *offset) /* {{{ */ { try_again: switch (Z_TYPE_P(offset)) { case IS_STRING: { zend_ulong index; if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), index)) { - return (zend_long) index; + return index; } break; } @@ -356,10 +356,22 @@ static zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */ return 0; } -static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset) +/* Returned index is an unsigned number such that we don't have to do a negative check. + * Negative numbers will be mapped at indices larger than ZEND_ULONG_MAX, + * which is beyond the maximum length. */ +static zend_always_inline zend_ulong spl_offset_convert_to_ulong(const zval *offset) { - zend_long index; + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + /* Allow skipping exception check at call-site. */ + ZEND_ASSERT(!EG(exception)); + return Z_LVAL_P(offset); + } else { + return spl_offset_convert_to_ulong_slow(offset); + } +} +static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset) +{ /* we have to return NULL on error here to avoid memleak because of * ZE duplicating uninitialized_zval_ptr */ if (!offset) { @@ -367,12 +379,12 @@ static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object * return NULL; } - index = spl_offset_convert_to_long(offset); - if (EG(exception)) { + zend_ulong index = spl_offset_convert_to_ulong(offset); + if (UNEXPECTED(EG(exception))) { return NULL; } - if (index < 0 || index >= intern->array.size) { + if (UNEXPECTED(index >= intern->array.size)) { zend_throw_exception(spl_ce_OutOfBoundsException, "Index invalid or out of range", 0); return NULL; } else { @@ -407,22 +419,19 @@ static zval *spl_fixedarray_object_read_dimension(zend_object *object, zval *off static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *intern, zval *offset, zval *value) { - zend_long index; - if (!offset) { /* '$array[] = value' syntax is not supported */ zend_throw_error(NULL, "[] operator not supported for SplFixedArray"); return; } - index = spl_offset_convert_to_long(offset); - if (EG(exception)) { + zend_ulong index = spl_offset_convert_to_ulong(offset); + if (UNEXPECTED(EG(exception))) { return; } - if (index < 0 || index >= intern->array.size) { + if (UNEXPECTED(index >= intern->array.size)) { zend_throw_exception(spl_ce_OutOfBoundsException, "Index invalid or out of range", 0); - return; } else { /* Fix #81429 */ zval *ptr = &(intern->array.elements[index]); @@ -452,16 +461,13 @@ static void spl_fixedarray_object_write_dimension(zend_object *object, zval *off static void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *intern, zval *offset) { - zend_long index; - - index = spl_offset_convert_to_long(offset); - if (EG(exception)) { + zend_ulong index = spl_offset_convert_to_ulong(offset); + if (UNEXPECTED(EG(exception))) { return; } - if (index < 0 || index >= intern->array.size) { + if (UNEXPECTED(index >= intern->array.size)) { zend_throw_exception(spl_ce_OutOfBoundsException, "Index invalid or out of range", 0); - return; } else { zval garbage; ZVAL_COPY_VALUE(&garbage, &intern->array.elements[index]); @@ -483,14 +489,12 @@ static void spl_fixedarray_object_unset_dimension(zend_object *object, zval *off static bool spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, bool check_empty) { - zend_long index; - - index = spl_offset_convert_to_long(offset); - if (EG(exception)) { + zend_ulong index = spl_offset_convert_to_ulong(offset); + if (UNEXPECTED(EG(exception))) { return false; } - if (index < 0 || index >= intern->array.size) { + if (index >= intern->array.size) { return false; } From 07470c3dd06e4090615c7b329a199b0b0dc3352f Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 30 Mar 2025 15:38:10 +0100 Subject: [PATCH 214/503] ext/pgsql: fix pg_close_stmt() signature. (#18194) --- ext/pgsql/pgsql.stub.php | 2 +- ext/pgsql/pgsql_arginfo.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/pgsql/pgsql.stub.php b/ext/pgsql/pgsql.stub.php index 22177fec367b3..cac22e3a30301 100644 --- a/ext/pgsql/pgsql.stub.php +++ b/ext/pgsql/pgsql.stub.php @@ -971,7 +971,7 @@ function pg_socket_poll($socket, int $read, int $write, int $timeout = -1): int function pg_set_chunked_rows_size(PgSql\Connection $connection, int $size): bool {} #endif #ifdef HAVE_PG_CLOSE_STMT - function pg_close_stmt(Pgsql\Connection $connection, string $statement_name): Pgsql\Result|false {} + function pg_close_stmt(Pgsql\Connection $connection, string $statement_name): PgSql\Result|false {} #endif } diff --git a/ext/pgsql/pgsql_arginfo.h b/ext/pgsql/pgsql_arginfo.h index cb79f83971301..336dd7ff86d04 100644 --- a/ext/pgsql/pgsql_arginfo.h +++ b/ext/pgsql/pgsql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 13be2a3c9a4ef4a72c0a67019b7400418752b603 */ + * Stub hash: 49e3493be11a5da1ed9a57339f14f92f34bf5d1b */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0) @@ -496,7 +496,7 @@ ZEND_END_ARG_INFO() #endif #if defined(HAVE_PG_CLOSE_STMT) -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_close_stmt, 0, 2, Pgsql\\Result, MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_close_stmt, 0, 2, PgSql\\Result, MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, connection, Pgsql\\Connection, 0) ZEND_ARG_TYPE_INFO(0, statement_name, IS_STRING, 0) ZEND_END_ARG_INFO() From d13d9b3c24ffeedaa114313eb184ea61323867f3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:09:01 +0200 Subject: [PATCH 215/503] Optimize SplFixedArray::toArray() (#18190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can use the optimized packed filling code instead of going through all the logic of the zend_hash update APIs. For this script: ```php $test = new SplFixedArray(4); $test[0] = 0; $test[1] = 1; $test[2] = 2; $test[3] = 3; for ($i = 0 ; $i< 5000000; $i++) $test->toArray(); ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php toarray.php Time (mean ± σ): 170.0 ms ± 1.8 ms [User: 167.3 ms, System: 2.2 ms] Range (min … max): 166.9 ms … 173.0 ms 17 runs Benchmark 2: ./sapi/cli/php_old toarray.php Time (mean ± σ): 215.7 ms ± 3.6 ms [User: 211.9 ms, System: 3.0 ms] Range (min … max): 211.3 ms … 222.0 ms 13 runs Summary ./sapi/cli/php toarray.php ran 1.27 ± 0.02 times faster than ./sapi/cli/php_old toarray.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php toarray.php Time (mean ± σ): 112.6 ms ± 1.4 ms [User: 109.6 ms, System: 2.9 ms] Range (min … max): 111.1 ms … 116.4 ms 25 runs Benchmark 2: ./sapi/cli/php_old toarray.php Time (mean ± σ): 145.3 ms ± 2.8 ms [User: 141.8 ms, System: 3.4 ms] Range (min … max): 142.6 ms … 151.8 ms 20 runs Summary ./sapi/cli/php toarray.php ran 1.29 ± 0.03 times faster than ./sapi/cli/php_old toarray.php ``` --- ext/spl/spl_fixedarray.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index fa846e48eee03..b0de1dc483626 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -695,11 +695,16 @@ PHP_METHOD(SplFixedArray, toArray) intern = Z_SPLFIXEDARRAY_P(ZEND_THIS); if (!spl_fixedarray_empty(&intern->array)) { - array_init(return_value); - for (zend_long i = 0; i < intern->array.size; i++) { - zend_hash_index_update(Z_ARRVAL_P(return_value), i, &intern->array.elements[i]); - Z_TRY_ADDREF(intern->array.elements[i]); - } + array_init_size(return_value, intern->array.size); + HashTable *ht = Z_ARRVAL_P(return_value); + zend_hash_real_init_packed(ht); + + ZEND_HASH_FILL_PACKED(ht) { + for (zend_long i = 0; i < intern->array.size; i++) { + ZEND_HASH_FILL_ADD(&intern->array.elements[i]); + Z_TRY_ADDREF(intern->array.elements[i]); + } + } ZEND_HASH_FILL_END(); } else { RETURN_EMPTY_ARRAY(); } From ce5d2f6d01f6152120c61d47b77ca45c89be2388 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:09:11 +0200 Subject: [PATCH 216/503] Make SplFixedArray::jsonSerialize() an implementation alias of SplFixedArray::toArray() (#18191) This reduces code duplication and can then use the optimized version. --- ext/spl/spl_fixedarray.c | 12 ------------ ext/spl/spl_fixedarray.stub.php | 3 +++ ext/spl/spl_fixedarray_arginfo.h | 5 ++--- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index b0de1dc483626..4efce87b1a9cd 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -881,18 +881,6 @@ PHP_METHOD(SplFixedArray, getIterator) zend_create_internal_iterator_zval(return_value, ZEND_THIS); } -PHP_METHOD(SplFixedArray, jsonSerialize) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(ZEND_THIS); - array_init_size(return_value, intern->array.size); - for (zend_long i = 0; i < intern->array.size; i++) { - zend_hash_next_index_insert_new(Z_ARR_P(return_value), &intern->array.elements[i]); - Z_TRY_ADDREF(intern->array.elements[i]); - } -} - static void spl_fixedarray_it_dtor(zend_object_iterator *iter) { zval_ptr_dtor(&iter->data); diff --git a/ext/spl/spl_fixedarray.stub.php b/ext/spl/spl_fixedarray.stub.php index a5a239ab4d69c..aa8aa5dbed188 100644 --- a/ext/spl/spl_fixedarray.stub.php +++ b/ext/spl/spl_fixedarray.stub.php @@ -55,5 +55,8 @@ public function offsetUnset($index): void {} public function getIterator(): Iterator {} + /** + * @implementation-alias SplFixedArray::toArray + */ public function jsonSerialize(): array {} } diff --git a/ext/spl/spl_fixedarray_arginfo.h b/ext/spl/spl_fixedarray_arginfo.h index 5d83183d91b81..c2ff9a77ac40f 100644 --- a/ext/spl/spl_fixedarray_arginfo.h +++ b/ext/spl/spl_fixedarray_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c01c9337e58601ff9e6c85072a62f68cc7fec9ba */ + * Stub hash: 0c838fed60b29671fe04e63315ab662d8cb16f0c */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SplFixedArray___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, size, IS_LONG, 0, "0") @@ -68,7 +68,6 @@ ZEND_METHOD(SplFixedArray, offsetGet); ZEND_METHOD(SplFixedArray, offsetSet); ZEND_METHOD(SplFixedArray, offsetUnset); ZEND_METHOD(SplFixedArray, getIterator); -ZEND_METHOD(SplFixedArray, jsonSerialize); static const zend_function_entry class_SplFixedArray_methods[] = { ZEND_ME(SplFixedArray, __construct, arginfo_class_SplFixedArray___construct, ZEND_ACC_PUBLIC) @@ -85,7 +84,7 @@ static const zend_function_entry class_SplFixedArray_methods[] = { ZEND_ME(SplFixedArray, offsetSet, arginfo_class_SplFixedArray_offsetSet, ZEND_ACC_PUBLIC) ZEND_ME(SplFixedArray, offsetUnset, arginfo_class_SplFixedArray_offsetUnset, ZEND_ACC_PUBLIC) ZEND_ME(SplFixedArray, getIterator, arginfo_class_SplFixedArray_getIterator, ZEND_ACC_PUBLIC) - ZEND_ME(SplFixedArray, jsonSerialize, arginfo_class_SplFixedArray_jsonSerialize, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("jsonSerialize", zim_SplFixedArray_toArray, arginfo_class_SplFixedArray_jsonSerialize, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_FE_END }; From 24fbe2d61eb6ce3c9aaf2154e711b59f8010b61a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:09:21 +0200 Subject: [PATCH 217/503] Micro-optimizations to str_increment() and str_decrement() (#18193) Since it's a new string we're returning we can use RETURN_NEW_STR() and we can also use zend_string_efree() for the strings that we replace because they have RC1. --- ext/standard/string.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index b15a24a098faa..1e20791eb61ce 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1273,10 +1273,10 @@ PHP_FUNCTION(str_increment) ZSTR_VAL(tmp)[0] = ZSTR_VAL(incremented)[0]; break; } - zend_string_release_ex(incremented, /* persistent */ false); - RETURN_STR(tmp); + zend_string_efree(incremented); + RETURN_NEW_STR(tmp); } - RETURN_STR(incremented); + RETURN_NEW_STR(incremented); } @@ -1323,17 +1323,17 @@ PHP_FUNCTION(str_decrement) if (UNEXPECTED(carry || (ZSTR_VAL(decremented)[0] == '0' && ZSTR_LEN(decremented) > 1))) { if (ZSTR_LEN(decremented) == 1) { - zend_string_release_ex(decremented, /* persistent */ false); + zend_string_efree(decremented); zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str)); RETURN_THROWS(); } zend_string *tmp = zend_string_alloc(ZSTR_LEN(decremented) - 1, 0); memcpy(ZSTR_VAL(tmp), ZSTR_VAL(decremented) + 1, ZSTR_LEN(decremented) - 1); ZSTR_VAL(tmp)[ZSTR_LEN(decremented) - 1] = '\0'; - zend_string_release_ex(decremented, /* persistent */ false); - RETURN_STR(tmp); + zend_string_efree(decremented); + RETURN_NEW_STR(tmp); } - RETURN_STR(decremented); + RETURN_NEW_STR(decremented); } #if defined(PHP_WIN32) From f056636086241fadd231751aef66f941a64109e7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:36:38 +0200 Subject: [PATCH 218/503] Avoid rebuilding the property table when possible in SplFixedArray's gc handler (#18195) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If there is not yet a dynamic property, and there are no class properties, then we know that we don't have to build a properties table. For this (micro-bench) script: ```php function x() { $fa = new SplFixedArray(1); $fa[0] = $fa; } for ($i=0;$i<1000000;$i++) x(); ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php spl.php Time (mean ± σ): 140.9 ms ± 1.2 ms [User: 137.5 ms, System: 2.7 ms] Range (min … max): 138.9 ms … 144.9 ms 21 runs Benchmark 2: ./sapi/cli/php_old spl.php Time (mean ± σ): 162.0 ms ± 3.8 ms [User: 157.7 ms, System: 3.2 ms] Range (min … max): 158.5 ms … 175.0 ms 17 runs Summary ./sapi/cli/php spl.php ran 1.15 ± 0.03 times faster than ./sapi/cli/php_old spl.php ``` --- ext/spl/spl_fixedarray.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 4efce87b1a9cd..b187949699087 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -212,12 +212,15 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) static HashTable* spl_fixedarray_object_get_gc(zend_object *obj, zval **table, int *n) { spl_fixedarray_object *intern = spl_fixed_array_from_obj(obj); - HashTable *ht = zend_std_get_properties(obj); *table = intern->array.elements; *n = (int)intern->array.size; - return ht; + if (obj->properties == NULL && obj->ce->default_properties_count == 0) { + return NULL; + } else { + return zend_std_get_properties(obj); + } } static HashTable* spl_fixedarray_object_get_properties_for(zend_object *obj, zend_prop_purpose purpose) From e034b69fa6f9f3ac9c409f108ae91b4f682660d7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 20:07:49 +0200 Subject: [PATCH 219/503] Optimize SplFixedArray::fromArray() for packed arrays (#18196) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the array is packed, then we don't have to loop to get the highest index. For this script: ```php $array = range(1, 100); for ($i=0;$i<1000000;$i++) { SplFixedArray::fromArray($array); } ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php spl.php Time (mean ± σ): 376.5 ms ± 2.0 ms [User: 372.1 ms, System: 2.6 ms] Range (min … max): 373.7 ms … 379.5 ms 10 runs Benchmark 2: ./sapi/cli/php_old spl.php Time (mean ± σ): 511.6 ms ± 1.9 ms [User: 508.0 ms, System: 2.3 ms] Range (min … max): 509.2 ms … 515.1 ms 10 runs Summary ./sapi/cli/php spl.php ran 1.36 ± 0.01 times faster than ./sapi/cli/php_old spl.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php spl.php Time (mean ± σ): 250.4 ms ± 3.5 ms [User: 246.6 ms, System: 2.6 ms] Range (min … max): 247.0 ms … 258.5 ms 11 runs Benchmark 2: ./sapi/cli/php_old spl.php Time (mean ± σ): 328.4 ms ± 1.0 ms [User: 324.4 ms, System: 3.8 ms] Range (min … max): 327.5 ms … 331.0 ms 10 runs Summary ./sapi/cli/php spl.php ran 1.31 ± 0.02 times faster than ./sapi/cli/php_old spl.php ``` Bonus: this also decreases the code size of the function. --- ext/spl/spl_fixedarray.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index b187949699087..99e6983b0ffc0 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -733,22 +733,29 @@ PHP_METHOD(SplFixedArray, fromArray) zend_ulong num_index, max_index = 0; zend_long tmp; - ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) { - if (str_index != NULL || (zend_long)num_index < 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys"); + if (HT_IS_PACKED(Z_ARRVAL_P(data))) { + /* If there are no holes, then nNumUsed is the number of elements. + * If there are holes, then nNumUsed is the index of the last element. */ + tmp = Z_ARRVAL_P(data)->nNumUsed; + } else { + ZEND_HASH_MAP_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) { + if (str_index != NULL || (zend_long)num_index < 0) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys"); + RETURN_THROWS(); + } + + if (num_index > max_index) { + max_index = num_index; + } + } ZEND_HASH_FOREACH_END(); + + tmp = max_index + 1; + if (tmp <= 0) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected"); RETURN_THROWS(); } - - if (num_index > max_index) { - max_index = num_index; - } - } ZEND_HASH_FOREACH_END(); - - tmp = max_index + 1; - if (tmp <= 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected"); - RETURN_THROWS(); } + spl_fixedarray_init(&array, tmp); ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), num_index, element) { From 5544a77f770f081224cb0fa426fc8020e6220223 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 20:22:35 +0000 Subject: [PATCH 220/503] Move definition of php_le_stream_context From ext/standard/file.h to main/streams/php_stream_context.h This reduces some dependency of main/ on ext/standard --- ext/standard/file.h | 1 - main/streams/php_stream_context.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/file.h b/ext/standard/file.h index 3a9cf1435b143..f8faebd028293 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -36,7 +36,6 @@ PHPAPI PHP_FUNCTION(fpassthru); PHP_MINIT_FUNCTION(user_streams); -PHPAPI int php_le_stream_context(void); PHPAPI zend_result php_copy_file(const char *src, const char *dest); PHPAPI zend_result php_copy_file_ex(const char *src, const char *dest, int src_flags); PHPAPI zend_result php_copy_file_ctx(const char *src, const char *dest, int src_flags, php_stream_context *ctx); diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h index d4ebe29bc162e..677bf14befeb2 100644 --- a/main/streams/php_stream_context.h +++ b/main/streams/php_stream_context.h @@ -53,6 +53,7 @@ struct _php_stream_context { }; BEGIN_EXTERN_C() +PHPAPI int php_le_stream_context(void); PHPAPI void php_stream_context_free(php_stream_context *context); PHPAPI php_stream_context *php_stream_context_alloc(void); PHPAPI zval *php_stream_context_get_option(php_stream_context *context, From 908490764b6b708ff06b1945f34568f44170ef16 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 20:23:27 +0000 Subject: [PATCH 221/503] main/streams: Add a helper macro to retrieve default context --- main/streams/php_stream_context.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h index 677bf14befeb2..a5325a94642c9 100644 --- a/main/streams/php_stream_context.h +++ b/main/streams/php_stream_context.h @@ -25,14 +25,17 @@ typedef void (*php_stream_notification_func)(php_stream_context *context, #define PHP_STREAM_NOTIFIER_PROGRESS 1 +/* TODO: Remove dependence on ext/standard/file.h for the default context global */ +#define php_stream_context_get_default(without_context) \ + (without_context) ? NULL : FG(default_context) ? FG(default_context) : \ + (FG(default_context) = php_stream_context_alloc()) + /* Attempt to fetch context from the zval passed, If no context was passed, use the default context The default context has not yet been created, do it now. */ #define php_stream_context_from_zval(zcontext, nocontext) ( \ (zcontext) ? zend_fetch_resource_ex(zcontext, "Stream-Context", php_le_stream_context()) : \ - (nocontext) ? NULL : \ - FG(default_context) ? FG(default_context) : \ - (FG(default_context) = php_stream_context_alloc()) ) + php_stream_context_get_default(nocontext)) #define php_stream_context_to_zval(context, zval) { ZVAL_RES(zval, (context)->res); GC_ADDREF((context)->res); } From 2244810dcf5d0deaa14cf101ab32f70e1e1fe941 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 17 Mar 2025 14:29:41 +0000 Subject: [PATCH 222/503] main/streams: Add a new helper function to get a php_stream from a zval without errors This is intended to replace the few manual usages of zend_fetch_resource2_ex() to fetch a php_stream from a zval. This will simplify the conversion from resource to object for streams when this actually happens. --- main/php_streams.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main/php_streams.h b/main/php_streams.h index f534bc27285f1..02281c3913fcd 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -285,6 +285,10 @@ END_EXTERN_C() #define php_stream_from_res_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2((res), "stream", php_file_le_stream(), php_file_le_pstream()) #define php_stream_from_zval_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2_ex((pzval), "stream", php_file_le_stream(), php_file_le_pstream()) +static zend_always_inline php_stream* php_stream_from_zval_no_verify_no_error(zval *zval) { + return (php_stream*)zend_fetch_resource2_ex(zval, NULL, php_file_le_stream(), php_file_le_pstream()); +} + BEGIN_EXTERN_C() static zend_always_inline bool php_stream_zend_parse_arg_into_stream( From 334d9bbc09e37d6f66dde23988df7d7299dc6f19 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 30 Mar 2025 19:34:52 +0100 Subject: [PATCH 223/503] ext/pgsql: adding pg_service() alongside other connection infos. returns the ongoing name of the service, if there is. available since postgres 18 close GH-18198 --- NEWS | 2 ++ UPGRADING | 1 + ext/pgsql/config.m4 | 3 +++ ext/pgsql/pgsql.c | 14 ++++++++++++++ ext/pgsql/pgsql.stub.php | 3 +++ ext/pgsql/pgsql_arginfo.h | 14 +++++++++++++- ext/pgsql/tests/pg_service.phpt | 19 +++++++++++++++++++ 7 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 ext/pgsql/tests/pg_service.phpt diff --git a/NEWS b/NEWS index 23bb612c482ca..dc91f999fb15e 100644 --- a/NEWS +++ b/NEWS @@ -110,6 +110,8 @@ PHP NEWS . pg_connect checks if connection_string contains any null byte, pg_close_stmt check if the statement contains any null byte. (David Carlier) + . Added pg_service to get the connection current service identifier. + (David Carlier) - POSIX: . Added POSIX_SC_OPEN_MAX constant to get the number of file descriptors diff --git a/UPGRADING b/UPGRADING index 7488912c88804..1a525f22f4411 100644 --- a/UPGRADING +++ b/UPGRADING @@ -273,6 +273,7 @@ PHP 8.5 UPGRADE NOTES . pg_close_stmt offers an alternative way to close a prepared statement from the DEALLOCATE sql command in that we can reuse its name afterwards. + . pg_service returns the ongoing service name of the connection. - Reflection: . ReflectionConstant::getFileName() was introduced. diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4 index 48fbbae34ace0..1409f879b52cc 100644 --- a/ext/pgsql/config.m4 +++ b/ext/pgsql/config.m4 @@ -31,6 +31,9 @@ if test "$PHP_PGSQL" != "no"; then PHP_CHECK_LIBRARY([pq], [PQclosePrepared], [AC_DEFINE([HAVE_PG_CLOSE_STMT], [1], [PostgreSQL 17 or later])],, [$PGSQL_LIBS]) + PHP_CHECK_LIBRARY([pq], [PQservice], + [AC_DEFINE([HAVE_PG_SERVICE], [1], [PostgreSQL 18 or later])],, + [$PGSQL_LIBS]) old_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $PGSQL_CFLAGS" diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 3f16c2e88f2fa..c53bf8ed9a35c 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -907,6 +907,7 @@ PHP_FUNCTION(pg_close) #define PHP_PG_HOST 6 #define PHP_PG_VERSION 7 #define PHP_PG_JIT 8 +#define PHP_PG_SERVICE 9 /* php_pgsql_get_link_info */ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) @@ -991,6 +992,12 @@ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type PQclear(res); return; } +#if defined(HAVE_PG_SERVICE) + case PHP_PG_SERVICE: { + result = PQservice(pgsql); + break; + } +#endif EMPTY_SWITCH_DEFAULT_CASE() } if (result) { @@ -1047,6 +1054,13 @@ PHP_FUNCTION(pg_jit) php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_JIT); } +#if defined(HAVE_PG_SERVICE) +PHP_FUNCTION(pg_service) +{ + php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_SERVICE); +} +#endif + /* Returns the value of a server parameter */ PHP_FUNCTION(pg_parameter_status) { diff --git a/ext/pgsql/pgsql.stub.php b/ext/pgsql/pgsql.stub.php index cac22e3a30301..04e648eff8d50 100644 --- a/ext/pgsql/pgsql.stub.php +++ b/ext/pgsql/pgsql.stub.php @@ -508,6 +508,9 @@ function pg_version(?PgSql\Connection $connection = null): array {} */ function pg_jit(?PgSql\Connection $connection = null): array {} +#ifdef HAVE_PG_SERVICE + function pg_service(?PgSql\Connection $connection = null): string {} +#endif /** * @param PgSql\Connection|string $connection * @refcount 1 diff --git a/ext/pgsql/pgsql_arginfo.h b/ext/pgsql/pgsql_arginfo.h index 336dd7ff86d04..cb58645e5e9f5 100644 --- a/ext/pgsql/pgsql_arginfo.h +++ b/ext/pgsql/pgsql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 49e3493be11a5da1ed9a57339f14f92f34bf5d1b */ + * Stub hash: 3cf44ca06d11cad086829d3d04900ade3cacb88b */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0) @@ -38,6 +38,12 @@ ZEND_END_ARG_INFO() #define arginfo_pg_jit arginfo_pg_version +#if defined(HAVE_PG_SERVICE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_service, 0, 0, IS_STRING, 0) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, connection, PgSql\\Connection, 1, "null") +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pg_parameter_status, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_INFO(0, connection) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -514,6 +520,9 @@ ZEND_FUNCTION(pg_tty); ZEND_FUNCTION(pg_host); ZEND_FUNCTION(pg_version); ZEND_FUNCTION(pg_jit); +#if defined(HAVE_PG_SERVICE) +ZEND_FUNCTION(pg_service); +#endif ZEND_FUNCTION(pg_parameter_status); ZEND_FUNCTION(pg_ping); ZEND_FUNCTION(pg_query); @@ -623,6 +632,9 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(pg_host, arginfo_pg_host) ZEND_FE(pg_version, arginfo_pg_version) ZEND_FE(pg_jit, arginfo_pg_jit) +#if defined(HAVE_PG_SERVICE) + ZEND_FE(pg_service, arginfo_pg_service) +#endif ZEND_FE(pg_parameter_status, arginfo_pg_parameter_status) ZEND_FE(pg_ping, arginfo_pg_ping) ZEND_FE(pg_query, arginfo_pg_query) diff --git a/ext/pgsql/tests/pg_service.phpt b/ext/pgsql/tests/pg_service.phpt new file mode 100644 index 0000000000000..0ce1be7285ebc --- /dev/null +++ b/ext/pgsql/tests/pg_service.phpt @@ -0,0 +1,19 @@ +--TEST-- +PostgreSQL connection service field support +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +string(%d) "%A" From cb245411b0b1b1559531e695c72b168e6f726cea Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com> Date: Mon, 31 Mar 2025 17:24:42 +0200 Subject: [PATCH 224/503] Add runtime-enabled heap debugging capabilities (#18172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debugging memory corruption issues in production can be difficult when it's not possible to use a debug build or ASAN/MSAN/Valgrind (e.g. for performance reasons). This change makes it possible to enable some basic heap debugging helpers without rebuilding PHP. This is controlled by the environment variable ZEND_MM_DEBUG. The env var takes a comma-separated list of parameters: - poison_free=byte: Override freed blocks with the specified byte value (represented as a number) - poison_alloc=byte: Override newly allocated blocks with the specified byte value (represented as a number) - padding=bytes: Pad allocated blocks with the specified amount of bytes (if non-zero, a value >= 16 is recommended to not break alignments) - check_freelists_on_shutdown=0|1: Enable checking freelist consistency [1] on shutdown Example: ZEND_MM_DEBUG=poison_free=0xbe,poison_alloc=0xeb,padding=16,check_freelists_on_shutdown=1 php ... This is implemented by installing custom handlers when ZEND_MM_DEBUG is set. This has zero overhead when ZEND_MM_DEBUG is not set. When ZEND_MM_DEBUG is set, the overhead is about 8.5% on the Symfony Demo benchmark. Goals: - Crash earlier after a memory corruption, to extract a useful backtrace - Be usable in production with reasonable overhead - Having zero overhead when not enabled Non-goals: - Replace debug builds, valgrind, ASAN, MSAN or other sanitizers [1] https://github.com/php/php-src/pull/14054 Co-authored-by: Tim Düsterhus --- Zend/zend_alloc.c | 228 +++++++++++++++++++- ext/zend_test/test.c | 14 ++ ext/zend_test/test.stub.php | 2 + ext/zend_test/test_arginfo.h | 6 +- ext/zend_test/tests/opline_dangling.phpt | 6 + ext/zend_test/tests/opline_dangling_02.phpt | 6 + 6 files changed, 259 insertions(+), 3 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 12e322d0347b3..b9f3bc015217c 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -305,7 +305,17 @@ struct _zend_mm_heap { size_t (*_gc)(void); void (*_shutdown)(bool full, bool silent); } custom_heap; - HashTable *tracked_allocs; + union { + HashTable *tracked_allocs; + struct { + bool poison_alloc; + uint8_t poison_alloc_value; + bool poison_free; + uint8_t poison_free_value; + uint8_t padding; + bool check_freelists_on_shutdown; + } debug; + }; #endif pid_t pid; zend_random_bytes_insecure_state rand_state; @@ -2389,8 +2399,19 @@ static void zend_mm_check_leaks(zend_mm_heap *heap) #if ZEND_MM_CUSTOM static void *tracked_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); static void tracked_free_all(zend_mm_heap *heap); +static void *poison_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); #endif +static void zend_mm_check_freelists(zend_mm_heap *heap) +{ + for (uint32_t bin_num = 0; bin_num < ZEND_MM_BINS; bin_num++) { + zend_mm_free_slot *slot = heap->free_slot[bin_num]; + while (slot) { + slot = zend_mm_get_next_free_slot(heap, bin_num, slot); + } + } +} + ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) { zend_mm_chunk *p; @@ -2555,8 +2576,9 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *ptr if (size_zv) { return Z_LVAL_P(size_zv); } + } else if (heap->custom_heap._malloc != poison_malloc) { + return 0; } - return 0; } #endif return zend_mm_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -3021,6 +3043,200 @@ static void tracked_free_all(zend_mm_heap *heap) { } #endif +static void* poison_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zend_mm_heap *heap = AG(mm_heap); + + if (SIZE_MAX - heap->debug.padding * 2 < size) { + zend_mm_panic("Integer overflow in memory allocation"); + } + size += heap->debug.padding * 2; + + void *ptr = zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + + if (EXPECTED(ptr)) { + if (heap->debug.poison_alloc) { + memset(ptr, heap->debug.poison_alloc_value, size); + } + + ptr = (char*)ptr + heap->debug.padding; + } + + return ptr; +} + +static void poison_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zend_mm_heap *heap = AG(mm_heap); + + if (EXPECTED(ptr)) { + /* zend_mm_shutdown() will try to free the heap when custom handlers + * are installed */ + if (UNEXPECTED(ptr == heap)) { + return; + } + + ptr = (char*)ptr - heap->debug.padding; + + size_t size = zend_mm_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + + if (heap->debug.poison_free) { + memset(ptr, heap->debug.poison_free_value, size); + } + } + + zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); +} + +static void* poison_realloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zend_mm_heap *heap = AG(mm_heap); + + void *new = poison_malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + + if (ptr) { + /* Determine the size of the old allocation from the unpadded pointer. */ + size_t oldsize = zend_mm_size(heap, (char*)ptr - heap->debug.padding ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + + /* Remove the padding size to determine the size that is available to the user. */ + oldsize -= (2 * heap->debug.padding); + +#if ZEND_DEBUG + oldsize -= sizeof(zend_mm_debug_info); +#endif + + memcpy(new, ptr, MIN(oldsize, size)); + poison_free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + + return new; +} + +static size_t poison_gc(void) +{ + zend_mm_heap *heap = AG(mm_heap); + + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + size_t (*_gc)(void); + void (*_shutdown)(bool, bool); + + zend_mm_get_custom_handlers_ex(heap, &_malloc, &_free, &_realloc, &_gc, &_shutdown); + zend_mm_set_custom_handlers_ex(heap, NULL, NULL, NULL, NULL, NULL); + + size_t collected = zend_mm_gc(heap); + + zend_mm_set_custom_handlers_ex(heap, _malloc, _free, _realloc, _gc, _shutdown); + + return collected; +} + +static void poison_shutdown(bool full, bool silent) +{ + zend_mm_heap *heap = AG(mm_heap); + + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + size_t (*_gc)(void); + void (*_shutdown)(bool, bool); + + zend_mm_get_custom_handlers_ex(heap, &_malloc, &_free, &_realloc, &_gc, &_shutdown); + zend_mm_set_custom_handlers_ex(heap, NULL, NULL, NULL, NULL, NULL); + + if (heap->debug.check_freelists_on_shutdown) { + zend_mm_check_freelists(heap); + } + + zend_mm_shutdown(heap, full, silent); + + if (!full) { + zend_mm_set_custom_handlers_ex(heap, _malloc, _free, _realloc, _gc, _shutdown); + } +} + +static void poison_enable(zend_mm_heap *heap, char *parameters) +{ + char *tmp = parameters; + char *end = tmp + strlen(tmp); + + /* Trim heading/trailing whitespaces */ + while (*tmp == ' ' || *tmp == '\t' || *tmp == '\n') { + tmp++; + } + while (end != tmp && (*(end-1) == ' ' || *(end-1) == '\t' || *(end-1) == '\n')) { + end--; + } + + if (tmp == end) { + return; + } + + while (1) { + char *key = tmp; + + tmp = memchr(tmp, '=', end - tmp); + if (!tmp) { + size_t key_len = end - key; + fprintf(stderr, "Unexpected EOF after ZEND_MM_DEBUG parameter '%.*s', expected '='\n", + (int)key_len, key); + return; + } + + size_t key_len = tmp - key; + char *value = tmp + 1; + + if (key_len == strlen("poison_alloc") + && !memcmp(key, "poison_alloc", key_len)) { + + heap->debug.poison_alloc = true; + heap->debug.poison_alloc_value = (uint8_t) ZEND_STRTOUL(value, &tmp, 0); + + } else if (key_len == strlen("poison_free") + && !memcmp(key, "poison_free", key_len)) { + + heap->debug.poison_free = true; + heap->debug.poison_free_value = (uint8_t) ZEND_STRTOUL(value, &tmp, 0); + + } else if (key_len == strlen("padding") + && !memcmp(key, "padding", key_len)) { + + uint8_t padding = ZEND_STRTOUL(value, &tmp, 0); + if (ZEND_MM_ALIGNED_SIZE(padding) != padding) { + fprintf(stderr, "ZEND_MM_DEBUG padding must be a multiple of %u, %u given\n", + (unsigned int)ZEND_MM_ALIGNMENT, + (unsigned int)padding); + return; + } + heap->debug.padding = padding; + + } else if (key_len == strlen("check_freelists_on_shutdown") + && !memcmp(key, "check_freelists_on_shutdown", key_len)) { + + heap->debug.check_freelists_on_shutdown = (bool) ZEND_STRTOUL(value, &tmp, 0); + + } else { + fprintf(stderr, "Unknown ZEND_MM_DEBUG parameter: '%.*s'\n", + (int)key_len, key); + return; + } + + if (tmp == end) { + break; + } + if (*tmp != ',') { + fprintf(stderr, "Unexpected '%c' after value of ZEND_MM_DEBUG parameter '%.*s', expected ','\n", + *tmp, (int)key_len, key); + return; + } + tmp++; + } + + zend_mm_set_custom_handlers_ex(heap, poison_malloc, poison_free, + poison_realloc, poison_gc, poison_shutdown); +} + static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) { char *tmp; @@ -3057,6 +3273,14 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) zend_mm_use_huge_pages = true; } alloc_globals->mm_heap = zend_mm_init(); + +#if ZEND_MM_CUSTOM + ZEND_ASSERT(!alloc_globals->mm_heap->tracked_allocs); + tmp = getenv("ZEND_MM_DEBUG"); + if (tmp) { + poison_enable(alloc_globals->mm_heap, tmp); + } +#endif } #ifdef ZTS diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index e3f87ee1e1636..565895dac72e1 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -15,6 +15,7 @@ */ #include "zend_modules.h" +#include "zend_types.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -182,6 +183,19 @@ static ZEND_FUNCTION(zend_leak_variable) Z_ADDREF_P(zv); } +static ZEND_FUNCTION(zend_delref) +{ + zval *zv; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) { + RETURN_THROWS(); + } + + Z_TRY_DELREF_P(zv); + + RETURN_NULL(); +} + /* Tests Z_PARAM_OBJ_OR_STR */ static ZEND_FUNCTION(zend_string_or_object) { diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 59cb9661e4e43..e0e1f32833ef5 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -235,6 +235,8 @@ function zend_leak_variable(mixed $variable): void {} function zend_leak_bytes(int $bytes = 3): void {} + function zend_delref(mixed $variable): void {} + function zend_string_or_object(object|string $param): object|string {} function zend_string_or_object_or_null(object|string|null $param): object|string|null {} diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index c558b58f65169..f13df2ae4bea2 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3082e62e96d5f4383c98638513463c676a7c3a69 */ + * Stub hash: 80b2dbc373baccd5ee4df047070d95e4c44effcd */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -42,6 +42,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_leak_bytes, 0, 0, IS_VOID, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, bytes, IS_LONG, 0, "3") ZEND_END_ARG_INFO() +#define arginfo_zend_delref arginfo_zend_leak_variable + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_zend_string_or_object, 0, 1, MAY_BE_OBJECT|MAY_BE_STRING) ZEND_ARG_TYPE_MASK(0, param, MAY_BE_OBJECT|MAY_BE_STRING, NULL) ZEND_END_ARG_INFO() @@ -264,6 +266,7 @@ static ZEND_FUNCTION(zend_create_unterminated_string); static ZEND_FUNCTION(zend_terminate_string); static ZEND_FUNCTION(zend_leak_variable); static ZEND_FUNCTION(zend_leak_bytes); +static ZEND_FUNCTION(zend_delref); static ZEND_FUNCTION(zend_string_or_object); static ZEND_FUNCTION(zend_string_or_object_or_null); static ZEND_FUNCTION(zend_string_or_stdclass); @@ -369,6 +372,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string) ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable) ZEND_FE(zend_leak_bytes, arginfo_zend_leak_bytes) + ZEND_FE(zend_delref, arginfo_zend_delref) ZEND_FE(zend_string_or_object, arginfo_zend_string_or_object) ZEND_FE(zend_string_or_object_or_null, arginfo_zend_string_or_object_or_null) ZEND_FE(zend_string_or_stdclass, arginfo_zend_string_or_stdclass) diff --git a/ext/zend_test/tests/opline_dangling.phpt b/ext/zend_test/tests/opline_dangling.phpt index 3b27b544ca34f..e8765c3048bb2 100644 --- a/ext/zend_test/tests/opline_dangling.phpt +++ b/ext/zend_test/tests/opline_dangling.phpt @@ -6,6 +6,12 @@ https://github.com/php/php-src/pull/12758 zend_test --ENV-- USE_ZEND_ALLOC=1 +--SKIPIF-- + --INI-- zend_test.observe_opline_in_zendmm=1 --FILE-- diff --git a/ext/zend_test/tests/opline_dangling_02.phpt b/ext/zend_test/tests/opline_dangling_02.phpt index 585a9c8395b59..8e0ace62db567 100644 --- a/ext/zend_test/tests/opline_dangling_02.phpt +++ b/ext/zend_test/tests/opline_dangling_02.phpt @@ -4,6 +4,12 @@ possible segfault in `ZEND_FUNC_GET_ARGS` zend_test --ENV-- USE_ZEND_ALLOC=1 +--SKIPIF-- + --INI-- zend_test.observe_opline_in_zendmm=1 --FILE-- From 6cd3863cf64fe0d3ffaa7fe8babe0c209586c750 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 18:11:02 +0000 Subject: [PATCH 225/503] ext/ffi: Remove duplicate assignment --- ext/ffi/ffi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 3fc97577abdea..6f629933fb2e4 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4150,7 +4150,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */ cdata->ptr = *(void**)ptr; } else if (old_type->kind == ZEND_FFI_TYPE_ARRAY && type->kind == ZEND_FFI_TYPE_POINTER - && zend_ffi_is_compatible_type(ZEND_FFI_TYPE(old_type->array.type), ZEND_FFI_TYPE(type->pointer.type))) { cdata->ptr = &cdata->ptr_holder; + && zend_ffi_is_compatible_type(ZEND_FFI_TYPE(old_type->array.type), ZEND_FFI_TYPE(type->pointer.type))) { cdata->ptr = &cdata->ptr_holder; cdata->ptr_holder = old_cdata->ptr; } else if (old_type->kind == ZEND_FFI_TYPE_POINTER From 73a31979e213719cb40ad4e2c874a13d89616274 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 17:22:29 +0000 Subject: [PATCH 226/503] ext/ffi: Prevent signed to unsigned comparisons --- ext/ffi/ffi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 6f629933fb2e4..275d1052cb90e 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -929,7 +929,7 @@ static void zend_ffi_callback_hash_dtor(zval *zv) /* {{{ */ if (callback_data->fcc.function_handler->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(callback_data->fcc.function_handler)); } - for (int i = 0; i < callback_data->arg_count; ++i) { + for (uint32_t i = 0; i < callback_data->arg_count; ++i) { if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) { efree(callback_data->arg_types[i]); } @@ -974,7 +974,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v } if (callback_data->arg_count) { - int n = 0; + uint32_t n = 0; for (n = 0; n < callback_data->arg_count; n++) { zval_ptr_dtor(&fci.params[n]); From 2ca0c2fd10239f2805f92f3acf448bc22cdb8adf Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 18:58:22 +0000 Subject: [PATCH 227/503] ext/ffi: Use 64bit integer to hold array length --- ext/ffi/ffi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 275d1052cb90e..401b80f25a191 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -6436,7 +6436,7 @@ static zend_result zend_ffi_validate_array_element_type(zend_ffi_type *type) /* void zend_ffi_make_array_type(zend_ffi_dcl *dcl, zend_ffi_val *len) /* {{{ */ { - int length = 0; + int64_t length = 0; zend_ffi_type *element_type; zend_ffi_type *type; From e5794774909e8e11a670e8061d9acc5dd3bbde88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 19:03:05 +0000 Subject: [PATCH 228/503] ext/ffi: Prevent variable shadowing --- ext/ffi/ffi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 401b80f25a191..50d6b1d46a767 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -6767,7 +6767,6 @@ void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl) /* { void zend_ffi_declare_tag(const char *name, size_t name_len, zend_ffi_dcl *dcl, bool incomplete) /* {{{ */ { zend_ffi_tag *tag; - zend_ffi_type *type; if (!FFI_G(tags)) { FFI_G(tags) = pemalloc(sizeof(HashTable), FFI_G(persistent)); @@ -6810,8 +6809,10 @@ void zend_ffi_declare_tag(const char *name, size_t name_len, zend_ffi_dcl *dcl, type->attr &= ~ZEND_FFI_ATTR_INCOMPLETE_TAG; } } else { - zend_ffi_tag *tag = pemalloc(sizeof(zend_ffi_tag), FFI_G(persistent)); zend_string *tag_name = zend_string_init(name, name_len, FFI_G(persistent)); + zend_ffi_type *type; + + tag = pemalloc(sizeof(zend_ffi_tag), FFI_G(persistent)); if (dcl->flags & ZEND_FFI_DCL_STRUCT) { tag->kind = ZEND_FFI_TAG_STRUCT; From 4059df0f2f3af326690efc2078f58266bd8b2deb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 17:55:57 +0000 Subject: [PATCH 229/503] ext/ffi: Reduce scope of variables --- ext/ffi/ffi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 50d6b1d46a767..42e48923da31f 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -974,9 +974,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v } if (callback_data->arg_count) { - uint32_t n = 0; - - for (n = 0; n < callback_data->arg_count; n++) { + for (uint32_t n = 0; n < callback_data->arg_count; n++) { zval_ptr_dtor(&fci.params[n]); } } @@ -3064,8 +3062,6 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ zend_string *lib = NULL; zend_ffi *ffi = NULL; DL_HANDLE handle = NULL; - char *err; - void *addr; ZEND_FFI_VALIDATE_API_RESTRICTION(); ZEND_PARSE_PARAMETERS_START(0, 2) @@ -3077,7 +3073,7 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ if (lib) { handle = DL_LOAD(ZSTR_VAL(lib)); if (!handle) { - err = GET_DL_ERROR(); + char *err = GET_DL_ERROR(); #ifdef PHP_WIN32 if (err && err[0]) { zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s' (%s)", ZSTR_VAL(lib), err); @@ -3125,6 +3121,7 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ zend_ffi_symbol *sym; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { + void *addr; if (sym->kind == ZEND_FFI_SYM_VAR) { addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); if (!addr) { @@ -3344,7 +3341,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ { struct stat buf; int fd; - char *code, *code_pos, *scope_name, *lib, *err; + char *code, *code_pos, *scope_name, *lib; size_t code_size, scope_name_len; zend_ffi *ffi; DL_HANDLE handle = NULL; @@ -3352,7 +3349,6 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ zend_string *name; zend_ffi_symbol *sym; zend_ffi_tag *tag; - void *addr; if (stat(filename, &buf) != 0) { if (preload) { @@ -3425,7 +3421,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ if (preload) { zend_error(E_WARNING, "FFI: Failed pre-loading '%s'", lib); } else { - err = GET_DL_ERROR(); + char *err = GET_DL_ERROR(); #ifdef PHP_WIN32 if (err && err[0]) { zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s' (%s)", lib, err); @@ -3459,6 +3455,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ if (FFI_G(symbols)) { ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { + void *addr; if (sym->kind == ZEND_FFI_SYM_VAR) { addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); if (!addr) { @@ -5952,15 +5949,13 @@ void zend_ffi_resolve_typedef(const char *name, size_t name_len, zend_ffi_dcl *d void zend_ffi_resolve_const(const char *name, size_t name_len, zend_ffi_val *val) /* {{{ */ { - zend_ffi_symbol *sym; - if (UNEXPECTED(FFI_G(attribute_parsing))) { val->kind = ZEND_FFI_VAL_NAME; val->str = name; val->len = name_len; return; } else if (FFI_G(symbols)) { - sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len); + zend_ffi_symbol *sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len); if (sym && sym->kind == ZEND_FFI_SYM_CONST) { val->i64 = sym->value; switch (sym->type->kind) { From f7a7e1c9ad70f775d5896a79909e2d19c9370739 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 28 Mar 2025 17:22:03 +0000 Subject: [PATCH 230/503] ext/ffi: Add const specifiers --- ext/ffi/ffi.c | 208 +++++++++++++++++++++++----------------------- ext/ffi/php_ffi.h | 46 +++++----- 2 files changed, 127 insertions(+), 127 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 42e48923da31f..c35dbc52934e4 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -220,14 +220,14 @@ static zend_internal_function zend_ffi_type_fn; /* forward declarations */ static void _zend_ffi_type_dtor(zend_ffi_type *type); static void zend_ffi_finalize_type(zend_ffi_dcl *dcl); -static bool zend_ffi_is_same_type(zend_ffi_type *type1, zend_ffi_type *type2); +static bool zend_ffi_is_same_type(const zend_ffi_type *type1, const zend_ffi_type *type2); static zend_ffi_type *zend_ffi_remember_type(zend_ffi_type *type); static char *zend_ffi_parse_directives(const char *filename, char *code_pos, char **scope_name, char **lib, bool preload); static ZEND_FUNCTION(ffi_trampoline); static ZEND_COLD void zend_ffi_return_unsupported(zend_ffi_type *type); static ZEND_COLD void zend_ffi_pass_unsupported(zend_ffi_type *type); -static ZEND_COLD void zend_ffi_assign_incompatible(zval *arg, zend_ffi_type *type); -static bool zend_ffi_is_compatible_type(zend_ffi_type *dst_type, zend_ffi_type *src_type); +static ZEND_COLD void zend_ffi_assign_incompatible(const zval *arg, const zend_ffi_type *type); +static bool zend_ffi_is_compatible_type(const zend_ffi_type *dst_type, const zend_ffi_type *src_type); #if FFI_CLOSURES static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value); @@ -270,7 +270,7 @@ static zend_object *zend_ffi_cdata_new(zend_class_entry *class_type) /* {{{ */ } /* }}} */ -static bool zend_ffi_func_ptr_are_compatible(zend_ffi_type *dst_type, zend_ffi_type *src_type) /* {{{ */ +static bool zend_ffi_func_ptr_are_compatible(const zend_ffi_type *dst_type, const zend_ffi_type *src_type) /* {{{ */ { uint32_t dst_argc, src_argc, i; zend_ffi_type *dst_arg, *src_arg; @@ -313,7 +313,7 @@ static bool zend_ffi_func_ptr_are_compatible(zend_ffi_type *dst_type, zend_ffi_t } /* }}} */ -static bool zend_ffi_is_compatible_type(zend_ffi_type *dst_type, zend_ffi_type *src_type) /* {{{ */ +static bool zend_ffi_is_compatible_type(const zend_ffi_type *dst_type, const zend_ffi_type *src_type) /* {{{ */ { while (1) { if (dst_type == src_type) { @@ -354,7 +354,7 @@ static bool zend_ffi_is_compatible_type(zend_ffi_type *dst_type, zend_ffi_type * } /* }}} */ -static ffi_type* zend_ffi_face_struct_add_fields(ffi_type* t, zend_ffi_type *type, int *i, size_t size) +static ffi_type* zend_ffi_face_struct_add_fields(ffi_type* t, const zend_ffi_type *type, int *i, size_t size) { zend_ffi_field *field; @@ -418,7 +418,7 @@ static ffi_type* zend_ffi_face_struct_add_fields(ffi_type* t, zend_ffi_type *typ return t; } -static ffi_type *zend_ffi_make_fake_struct_type(zend_ffi_type *type) /* {{{ */ +static ffi_type *zend_ffi_make_fake_struct_type(const zend_ffi_type *type) /* {{{ */ { /* for unions we use only the first field */ uint32_t num_fields = !(type->attr & ZEND_FFI_ATTR_UNION) ? @@ -438,7 +438,7 @@ static ffi_type *zend_ffi_make_fake_struct_type(zend_ffi_type *type) /* {{{ */ } /* }}} */ -static ffi_type *zend_ffi_get_type(zend_ffi_type *type) /* {{{ */ +static ffi_type *zend_ffi_get_type(const zend_ffi_type *type) /* {{{ */ { zend_ffi_type_kind kind = type->kind; @@ -633,7 +633,7 @@ static zend_always_inline void zend_ffi_cdata_to_zval(zend_ffi_cdata *cdata, voi } /* }}} */ -static uint64_t zend_ffi_bit_field_read(void *ptr, zend_ffi_field *field) /* {{{ */ +static uint64_t zend_ffi_bit_field_read(void *ptr, const zend_ffi_field *field) /* {{{ */ { size_t bit = field->first_bit; size_t last_bit = bit + field->bits - 1; @@ -675,7 +675,7 @@ static uint64_t zend_ffi_bit_field_read(void *ptr, zend_ffi_field *field) /* {{{ } /* }}} */ -static void zend_ffi_bit_field_to_zval(void *ptr, zend_ffi_field *field, zval *rv) /* {{{ */ +static void zend_ffi_bit_field_to_zval(void *ptr, const zend_ffi_field *field, zval *rv) /* {{{ */ { uint64_t val = zend_ffi_bit_field_read(ptr, field); if (ZEND_FFI_TYPE(field->type)->kind == ZEND_FFI_TYPE_CHAR @@ -693,7 +693,7 @@ static void zend_ffi_bit_field_to_zval(void *ptr, zend_ffi_field *field, zval *r } /* }}} */ -static void zend_ffi_zval_to_bit_field(void *ptr, zend_ffi_field *field, zval *value) /* {{{ */ +static void zend_ffi_zval_to_bit_field(void *ptr, const zend_ffi_field *field, const zval *value) /* {{{ */ { uint64_t val = zval_get_long(value); size_t bit = field->first_bit; @@ -744,7 +744,7 @@ static zend_always_inline zend_result zend_ffi_zval_to_cdata(void *ptr, zend_ffi /* Pointer type has special handling of CData */ if (kind != ZEND_FFI_TYPE_POINTER && Z_TYPE_P(value) == IS_OBJECT && Z_OBJCE_P(value) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(value); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(value); if (zend_ffi_is_compatible_type(type, ZEND_FFI_TYPE(cdata->type)) && type->size == ZEND_FFI_TYPE(cdata->type)->size) { memcpy(ptr, cdata->ptr, type->size); @@ -822,7 +822,7 @@ static zend_always_inline zend_result zend_ffi_zval_to_cdata(void *ptr, zend_ffi *(void**)ptr = NULL; break; } else if (Z_TYPE_P(value) == IS_OBJECT && Z_OBJCE_P(value) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(value); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(value); if (zend_ffi_is_compatible_type(type, ZEND_FFI_TYPE(cdata->type))) { if (ZEND_FFI_TYPE(cdata->type)->kind == ZEND_FFI_TYPE_POINTER) { @@ -1170,8 +1170,8 @@ static zval *zend_ffi_cdata_set(zend_object *obj, zend_string *member, zval *val static zend_result zend_ffi_cdata_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { if (type == IS_STRING) { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)readobj; - zend_ffi_type *ctype = ZEND_FFI_TYPE(cdata->type); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)readobj; + const zend_ffi_type *ctype = ZEND_FFI_TYPE(cdata->type); void *ptr = cdata->ptr; zend_ffi_type_kind kind = ctype->kind; @@ -1698,7 +1698,7 @@ static ZEND_COLD void zend_ffi_pass_unsupported(zend_ffi_type *type) /* {{{ */ } /* }}} */ -static ZEND_COLD void zend_ffi_pass_incompatible(zval *arg, zend_ffi_type *type, uint32_t n, zend_execute_data *execute_data) /* {{{ */ +static ZEND_COLD void zend_ffi_pass_incompatible(const zval *arg, const zend_ffi_type *type, uint32_t n, const zend_execute_data *execute_data) /* {{{ */ { zend_ffi_ctype_name_buf buf1, buf2; @@ -1708,7 +1708,7 @@ static ZEND_COLD void zend_ffi_pass_incompatible(zval *arg, zend_ffi_type *type, } else { *buf1.end = 0; if (Z_TYPE_P(arg) == IS_OBJECT && Z_OBJCE_P(arg) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(arg); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(arg); type = ZEND_FFI_TYPE(cdata->type); buf2.start = buf2.end = buf2.buf + ((MAX_TYPE_NAME_LEN * 3) / 4); @@ -1725,7 +1725,7 @@ static ZEND_COLD void zend_ffi_pass_incompatible(zval *arg, zend_ffi_type *type, } /* }}} */ -static ZEND_COLD void zend_ffi_assign_incompatible(zval *arg, zend_ffi_type *type) /* {{{ */ +static ZEND_COLD void zend_ffi_assign_incompatible(const zval *arg, const zend_ffi_type *type) /* {{{ */ { zend_ffi_ctype_name_buf buf1, buf2; @@ -1735,7 +1735,7 @@ static ZEND_COLD void zend_ffi_assign_incompatible(zval *arg, zend_ffi_type *typ } else { *buf1.end = 0; if (Z_TYPE_P(arg) == IS_OBJECT && Z_OBJCE_P(arg) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(arg); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ_P(arg); type = ZEND_FFI_TYPE(cdata->type); buf2.start = buf2.end = buf2.buf + ((MAX_TYPE_NAME_LEN * 3) / 4); @@ -1768,7 +1768,7 @@ static zend_string *zend_ffi_get_class_name(zend_string *prefix, const zend_ffi_ static zend_string *zend_ffi_cdata_get_class_name(const zend_object *zobj) /* {{{ */ { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)zobj; + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)zobj; return zend_ffi_get_class_name(zobj->ce->name, ZEND_FFI_TYPE(cdata->type)); } @@ -1778,10 +1778,10 @@ static int zend_ffi_cdata_compare_objects(zval *o1, zval *o2) /* {{{ */ { if (Z_TYPE_P(o1) == IS_OBJECT && Z_OBJCE_P(o1) == zend_ffi_cdata_ce && Z_TYPE_P(o2) == IS_OBJECT && Z_OBJCE_P(o2) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata1 = (zend_ffi_cdata*)Z_OBJ_P(o1); - zend_ffi_cdata *cdata2 = (zend_ffi_cdata*)Z_OBJ_P(o2); - zend_ffi_type *type1 = ZEND_FFI_TYPE(cdata1->type); - zend_ffi_type *type2 = ZEND_FFI_TYPE(cdata2->type); + const zend_ffi_cdata *cdata1 = (zend_ffi_cdata*)Z_OBJ_P(o1); + const zend_ffi_cdata *cdata2 = (zend_ffi_cdata*)Z_OBJ_P(o2); + const zend_ffi_type *type1 = ZEND_FFI_TYPE(cdata1->type); + const zend_ffi_type *type2 = ZEND_FFI_TYPE(cdata2->type); if (type1->kind == ZEND_FFI_TYPE_POINTER && type2->kind == ZEND_FFI_TYPE_POINTER) { void *ptr1 = *(void**)cdata1->ptr; @@ -1801,8 +1801,8 @@ static int zend_ffi_cdata_compare_objects(zval *o1, zval *o2) /* {{{ */ static zend_result zend_ffi_cdata_count_elements(zend_object *obj, zend_long *count) /* {{{ */ { - zend_ffi_cdata *cdata = (zend_ffi_cdata*)obj; - zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)obj; + const zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); if (type->kind != ZEND_FFI_TYPE_ARRAY) { zend_throw_error(zend_ffi_exception_ce, "Attempt to count() on non C array"); @@ -1890,8 +1890,8 @@ static zend_result zend_ffi_cdata_do_operation(uint8_t opcode, zval *result, zva return SUCCESS; } else if (opcode == ZEND_SUB) { if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJCE_P(op2) == zend_ffi_cdata_ce) { - zend_ffi_cdata *cdata2 = (zend_ffi_cdata*)Z_OBJ_P(op2); - zend_ffi_type *type2 = ZEND_FFI_TYPE(cdata2->type); + const zend_ffi_cdata *cdata2 = (zend_ffi_cdata*)Z_OBJ_P(op2); + const zend_ffi_type *type2 = ZEND_FFI_TYPE(cdata2->type); if (type2->kind == ZEND_FFI_TYPE_POINTER || type2->kind == ZEND_FFI_TYPE_ARRAY) { zend_ffi_type *t1, *t2; @@ -1959,9 +1959,9 @@ static void zend_ffi_cdata_it_dtor(zend_object_iterator *iter) /* {{{ */ static zend_result zend_ffi_cdata_it_valid(zend_object_iterator *it) /* {{{ */ { - zend_ffi_cdata_iterator *iter = (zend_ffi_cdata_iterator*)it; - zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ(iter->it.data); - zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); + const zend_ffi_cdata_iterator *iter = (zend_ffi_cdata_iterator*)it; + const zend_ffi_cdata *cdata = (zend_ffi_cdata*)Z_OBJ(iter->it.data); + const zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); return (iter->key >= 0 && iter->key < type->array.length) ? SUCCESS : FAILURE; } @@ -1997,7 +1997,7 @@ static zval *zend_ffi_cdata_it_get_current_data(zend_object_iterator *it) /* {{{ static void zend_ffi_cdata_it_get_current_key(zend_object_iterator *it, zval *key) /* {{{ */ { - zend_ffi_cdata_iterator *iter = (zend_ffi_cdata_iterator*)it; + const zend_ffi_cdata_iterator *iter = (zend_ffi_cdata_iterator*)it; ZVAL_LONG(key, iter->key); } /* }}} */ @@ -2238,7 +2238,7 @@ static void zend_ffi_ctype_free_obj(zend_object *object) /* {{{ */ } /* }}} */ -static bool zend_ffi_is_same_type(zend_ffi_type *type1, zend_ffi_type *type2) /* {{{ */ +static bool zend_ffi_is_same_type(const zend_ffi_type *type1, const zend_ffi_type *type2) /* {{{ */ { while (1) { if (type1 == type2) { @@ -2280,10 +2280,10 @@ static int zend_ffi_ctype_compare_objects(zval *o1, zval *o2) /* {{{ */ { if (Z_TYPE_P(o1) == IS_OBJECT && Z_OBJCE_P(o1) == zend_ffi_ctype_ce && Z_TYPE_P(o2) == IS_OBJECT && Z_OBJCE_P(o2) == zend_ffi_ctype_ce) { - zend_ffi_ctype *ctype1 = (zend_ffi_ctype*)Z_OBJ_P(o1); - zend_ffi_ctype *ctype2 = (zend_ffi_ctype*)Z_OBJ_P(o2); - zend_ffi_type *type1 = ZEND_FFI_TYPE(ctype1->type); - zend_ffi_type *type2 = ZEND_FFI_TYPE(ctype2->type); + const zend_ffi_ctype *ctype1 = (zend_ffi_ctype*)Z_OBJ_P(o1); + const zend_ffi_ctype *ctype2 = (zend_ffi_ctype*)Z_OBJ_P(o2); + const zend_ffi_type *type1 = ZEND_FFI_TYPE(ctype1->type); + const zend_ffi_type *type2 = ZEND_FFI_TYPE(ctype2->type); if (zend_ffi_is_same_type(type1, type2)) { return 0; @@ -2567,7 +2567,7 @@ static zval *zend_ffi_write_var(zend_object *obj, zend_string *var_name, zval *v } /* }}} */ -static zend_result zend_ffi_pass_arg(zval *arg, zend_ffi_type *type, ffi_type **pass_type, void **arg_values, uint32_t n, zend_execute_data *execute_data) /* {{{ */ +static zend_result zend_ffi_pass_arg(zval *arg, zend_ffi_type *type, ffi_type **pass_type, void **arg_values, uint32_t n, const zend_execute_data *execute_data) /* {{{ */ { zend_long lval; double dval; @@ -2710,7 +2710,7 @@ static zend_result zend_ffi_pass_arg(zval *arg, zend_ffi_type *type, ffi_type ** } /* }}} */ -static zend_result zend_ffi_pass_var_arg(zval *arg, ffi_type **pass_type, void **arg_values, uint32_t n, zend_execute_data *execute_data) /* {{{ */ +static zend_result zend_ffi_pass_var_arg(zval *arg, ffi_type **pass_type, void **arg_values, uint32_t n, const zend_execute_data *execute_data) /* {{{ */ { ZVAL_DEREF(arg); switch (Z_TYPE_P(arg)) { @@ -2998,7 +2998,7 @@ static zend_never_inline int zend_ffi_disabled(void) /* {{{ */ } /* }}} */ -static zend_always_inline bool zend_ffi_validate_api_restriction(zend_execute_data *execute_data) /* {{{ */ +static zend_always_inline bool zend_ffi_validate_api_restriction(const zend_execute_data *execute_data) /* {{{ */ { if (EXPECTED(FFI_G(restriction) > ZEND_FFI_ENABLED)) { ZEND_ASSERT(FFI_G(restriction) == ZEND_FFI_PRELOAD); @@ -3156,7 +3156,7 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ } /* }}} */ -static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ */ +static bool zend_ffi_same_types(const zend_ffi_type *old, const zend_ffi_type *type) /* {{{ */ { if (old == type) { return 1; @@ -3183,7 +3183,7 @@ static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ } else { zend_ffi_field *old_field, *field; zend_string *key; - Bucket *b = type->record.fields.arData; + const Bucket *b = type->record.fields.arData; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&old->record.fields, key, old_field) { while (Z_TYPE(b->val) == IS_UNDEF) { @@ -3217,7 +3217,7 @@ static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ return 0; } else if (old->func.args) { zend_ffi_type *arg_type; - zval *zv = type->func.args->arPacked; + const zval *zv = type->func.args->arPacked; ZEND_HASH_PACKED_FOREACH_PTR(old->func.args, arg_type) { while (Z_TYPE_P(zv) == IS_UNDEF) { @@ -3238,7 +3238,7 @@ static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ } /* }}} */ -static bool zend_ffi_same_symbols(zend_ffi_symbol *old, zend_ffi_symbol *sym) /* {{{ */ +static bool zend_ffi_same_symbols(const zend_ffi_symbol *old, const zend_ffi_symbol *sym) /* {{{ */ { if (old->kind != sym->kind || old->is_const != sym->is_const) { return 0; @@ -3254,7 +3254,7 @@ static bool zend_ffi_same_symbols(zend_ffi_symbol *old, zend_ffi_symbol *sym) /* } /* }}} */ -static bool zend_ffi_same_tags(zend_ffi_tag *old, zend_ffi_tag *tag) /* {{{ */ +static bool zend_ffi_same_tags(const zend_ffi_tag *old, const zend_ffi_tag *tag) /* {{{ */ { if (old->kind != tag->kind) { return 0; @@ -3699,7 +3699,7 @@ static void zend_ffi_throw_parser_error(const char *format, ...) /* {{{ */ } /* }}} */ -static zend_result zend_ffi_validate_vla(zend_ffi_type *type) /* {{{ */ +static zend_result zend_ffi_validate_vla(const zend_ffi_type *type) /* {{{ */ { if (!FFI_G(allow_vla) && (type->attr & ZEND_FFI_ATTR_VLA)) { zend_ffi_throw_parser_error("\"[*]\" is not allowed in other than function prototype scope at line %d", FFI_G(line)); @@ -3709,7 +3709,7 @@ static zend_result zend_ffi_validate_vla(zend_ffi_type *type) /* {{{ */ } /* }}} */ -static zend_result zend_ffi_validate_incomplete_type(zend_ffi_type *type, bool allow_incomplete_tag, bool allow_incomplete_array) /* {{{ */ +static zend_result zend_ffi_validate_incomplete_type(const zend_ffi_type *type, bool allow_incomplete_tag, bool allow_incomplete_array) /* {{{ */ { if (!allow_incomplete_tag && (type->attr & ZEND_FFI_ATTR_INCOMPLETE_TAG)) { if (FFI_G(tags)) { @@ -3753,7 +3753,7 @@ static zend_result zend_ffi_validate_incomplete_type(zend_ffi_type *type, bool a } /* }}} */ -static zend_result zend_ffi_validate_type(zend_ffi_type *type, bool allow_incomplete_tag, bool allow_incomplete_array) /* {{{ */ +static zend_result zend_ffi_validate_type(const zend_ffi_type *type, bool allow_incomplete_tag, bool allow_incomplete_array) /* {{{ */ { if (type->kind == ZEND_FFI_TYPE_VOID) { zend_ffi_throw_parser_error("void type is not allowed at line %d", FFI_G(line)); @@ -3763,7 +3763,7 @@ static zend_result zend_ffi_validate_type(zend_ffi_type *type, bool allow_incomp } /* }}} */ -static zend_result zend_ffi_validate_var_type(zend_ffi_type *type, bool allow_incomplete_array) /* {{{ */ +static zend_result zend_ffi_validate_var_type(const zend_ffi_type *type, bool allow_incomplete_array) /* {{{ */ { if (type->kind == ZEND_FFI_TYPE_FUNC) { zend_ffi_throw_parser_error("function type is not allowed at line %d", FFI_G(line)); @@ -4732,8 +4732,8 @@ ZEND_METHOD(FFI_CType, getName) /* {{{ */ ZEND_METHOD(FFI_CType, getKind) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4746,8 +4746,8 @@ ZEND_METHOD(FFI_CType, getKind) /* {{{ */ ZEND_METHOD(FFI_CType, getSize) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4760,8 +4760,8 @@ ZEND_METHOD(FFI_CType, getSize) /* {{{ */ ZEND_METHOD(FFI_CType, getAlignment) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4774,8 +4774,8 @@ ZEND_METHOD(FFI_CType, getAlignment) /* {{{ */ ZEND_METHOD(FFI_CType, getAttributes) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4788,8 +4788,8 @@ ZEND_METHOD(FFI_CType, getAttributes) /* {{{ */ ZEND_METHOD(FFI_CType, getEnumKind) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4828,8 +4828,8 @@ ZEND_METHOD(FFI_CType, getArrayElementType) /* {{{ */ ZEND_METHOD(FFI_CType, getArrayLength) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4868,8 +4868,8 @@ ZEND_METHOD(FFI_CType, getPointerType) /* {{{ */ ZEND_METHOD(FFI_CType, getStructFieldNames) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; HashTable *ht; zend_string* name; zval zv; @@ -4895,10 +4895,10 @@ ZEND_METHOD(FFI_CType, getStructFieldNames) /* {{{ */ ZEND_METHOD(FFI_CType, getStructFieldOffset) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; zend_string *name; - zend_ffi_field *ptr; + const zend_ffi_field *ptr; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STR(name) @@ -4951,8 +4951,8 @@ ZEND_METHOD(FFI_CType, getStructFieldType) /* {{{ */ ZEND_METHOD(FFI_CType, getFuncABI) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -4991,8 +4991,8 @@ ZEND_METHOD(FFI_CType, getFuncReturnType) /* {{{ */ ZEND_METHOD(FFI_CType, getFuncParameterCount) /* {{{ */ { - zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - zend_ffi_type *type; + const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + const zend_ffi_type *type; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -5906,8 +5906,8 @@ static void zend_ffi_finalize_type(zend_ffi_dcl *dcl) /* {{{ */ bool zend_ffi_is_typedef_name(const char *name, size_t name_len) /* {{{ */ { - zend_ffi_symbol *sym; - zend_ffi_type *type; + const zend_ffi_symbol *sym; + const zend_ffi_type *type; if (FFI_G(symbols)) { sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len); @@ -5955,7 +5955,7 @@ void zend_ffi_resolve_const(const char *name, size_t name_len, zend_ffi_val *val val->len = name_len; return; } else if (FFI_G(symbols)) { - zend_ffi_symbol *sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len); + const zend_ffi_symbol *sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len); if (sym && sym->kind == ZEND_FFI_SYM_CONST) { val->i64 = sym->value; switch (sym->type->kind) { @@ -6005,7 +6005,7 @@ void zend_ffi_make_enum_type(zend_ffi_dcl *dcl) /* {{{ */ } /* }}} */ -void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name_len, zend_ffi_val *val, int64_t *min, int64_t *max, int64_t *last) /* {{{ */ +void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name_len, const zend_ffi_val *val, int64_t *min, int64_t *max, int64_t *last) /* {{{ */ { zend_ffi_symbol *sym; const zend_ffi_type *sym_type; @@ -6136,7 +6136,7 @@ void zend_ffi_make_struct_type(zend_ffi_dcl *dcl) /* {{{ */ static zend_result zend_ffi_validate_prev_field_type(zend_ffi_type *struct_type) /* {{{ */ { if (zend_hash_num_elements(&struct_type->record.fields) > 0) { - zend_ffi_field *field = NULL; + const zend_ffi_field *field = NULL; ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&struct_type->record.fields, field) { break; @@ -6150,7 +6150,7 @@ static zend_result zend_ffi_validate_prev_field_type(zend_ffi_type *struct_type) } /* }}} */ -static zend_result zend_ffi_validate_field_type(zend_ffi_type *type, zend_ffi_type *struct_type) /* {{{ */ +static zend_result zend_ffi_validate_field_type(const zend_ffi_type *type, zend_ffi_type *struct_type) /* {{{ */ { if (type == struct_type) { zend_ffi_throw_parser_error("Struct/union can't contain an instance of itself at line %d", FFI_G(line)); @@ -6279,7 +6279,7 @@ void zend_ffi_add_anonymous_field(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_ } /* }}} */ -void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl, zend_ffi_val *bits) /* {{{ */ +void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl, const zend_ffi_val *bits) /* {{{ */ { zend_ffi_type *struct_type = ZEND_FFI_TYPE(struct_dcl->type); zend_ffi_type *field_type; @@ -6342,7 +6342,7 @@ void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t n struct_type->size = MAX(struct_type->size, ((bits->u64 + 31) / 32) * 4); } } else { - zend_ffi_field *prev_field = NULL; + const zend_ffi_field *prev_field = NULL; if (zend_hash_num_elements(&struct_type->record.fields) > 0) { ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&struct_type->record.fields, prev_field) { @@ -6416,7 +6416,7 @@ void zend_ffi_make_pointer_type(zend_ffi_dcl *dcl) /* {{{ */ } /* }}} */ -static zend_result zend_ffi_validate_array_element_type(zend_ffi_type *type) /* {{{ */ +static zend_result zend_ffi_validate_array_element_type(const zend_ffi_type *type) /* {{{ */ { if (type->kind == ZEND_FFI_TYPE_FUNC) { zend_ffi_throw_parser_error("Array of functions is not allowed at line %d", FFI_G(line)); @@ -6429,10 +6429,10 @@ static zend_result zend_ffi_validate_array_element_type(zend_ffi_type *type) /* } /* }}} */ -void zend_ffi_make_array_type(zend_ffi_dcl *dcl, zend_ffi_val *len) /* {{{ */ +void zend_ffi_make_array_type(zend_ffi_dcl *dcl, const zend_ffi_val *len) /* {{{ */ { int64_t length = 0; - zend_ffi_type *element_type; + const zend_ffi_type *element_type; zend_ffi_type *type; zend_ffi_finalize_type(dcl); @@ -6476,7 +6476,7 @@ void zend_ffi_make_array_type(zend_ffi_dcl *dcl, zend_ffi_val *len) /* {{{ */ } /* }}} */ -static zend_result zend_ffi_validate_func_ret_type(zend_ffi_type *type) /* {{{ */ +static zend_result zend_ffi_validate_func_ret_type(const zend_ffi_type *type) /* {{{ */ { if (type->kind == ZEND_FFI_TYPE_FUNC) { zend_ffi_throw_parser_error("Function returning function is not allowed at line %d", FFI_G(line)); @@ -6690,7 +6690,7 @@ void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl) /* { return; } else if ((dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == 0 || (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_EXTERN) { - zend_ffi_type *type = ZEND_FFI_TYPE(dcl->type); + const zend_ffi_type *type = ZEND_FFI_TYPE(dcl->type); if (type->kind == ZEND_FFI_TYPE_FUNC) { if (sym->kind == ZEND_FFI_SYM_FUNC @@ -6955,7 +6955,7 @@ void zend_ffi_add_attribute(zend_ffi_dcl *dcl, const char *name, size_t name_len _(format) \ _(deprecated) -void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, zend_ffi_val *val) /* {{{ */ +void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, const zend_ffi_val *val) /* {{{ */ { enum { VALUE_ATTRIBUTES(ATTR_ID) @@ -7070,7 +7070,7 @@ void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t na } /* }}} */ -void zend_ffi_add_msvc_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, zend_ffi_val *val) /* {{{ */ +void zend_ffi_add_msvc_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, const zend_ffi_val *val) /* {{{ */ { if (name_len == sizeof("align")-1 && memcmp(name, "align", sizeof("align")-1) == 0) { if ((val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_INT64 || val->kind == ZEND_FFI_VAL_UINT64) @@ -7152,7 +7152,7 @@ void zend_ffi_align_as_type(zend_ffi_dcl *dcl, zend_ffi_dcl *align_dcl) /* {{{ * } /* }}} */ -void zend_ffi_align_as_val(zend_ffi_dcl *dcl, zend_ffi_val *align_val) /* {{{ */ +void zend_ffi_align_as_val(zend_ffi_dcl *dcl, const zend_ffi_val *align_val) /* {{{ */ { switch (align_val->kind) { case ZEND_FFI_VAL_INT32: @@ -7396,7 +7396,7 @@ void zend_ffi_align_as_val(zend_ffi_dcl *dcl, zend_ffi_val *align_val) /* {{{ */ } \ } while (0) -void zend_ffi_expr_conditional(zend_ffi_val *val, zend_ffi_val *op2, zend_ffi_val *op3) /* {{{ */ +void zend_ffi_expr_conditional(zend_ffi_val *val, const zend_ffi_val *op2, const zend_ffi_val *op3) /* {{{ */ { zend_ffi_expr_bool(val); if (val->kind == ZEND_FFI_VAL_INT32) { @@ -7433,97 +7433,97 @@ void zend_ffi_expr_bool_and(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ } /* }}} */ -void zend_ffi_expr_bw_or(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_bw_or(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, |); } /* }}} */ -void zend_ffi_expr_bw_xor(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_bw_xor(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, ^); } /* }}} */ -void zend_ffi_expr_bw_and(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_bw_and(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, &); } /* }}} */ -void zend_ffi_expr_is_equal(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_equal(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, ==); } /* }}} */ -void zend_ffi_expr_is_not_equal(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_not_equal(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, !=); } /* }}} */ -void zend_ffi_expr_is_less(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_less(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, <); } /* }}} */ -void zend_ffi_expr_is_greater(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_greater(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, >); } /* }}} */ -void zend_ffi_expr_is_less_or_equal(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_less_or_equal(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, <=); } /* }}} */ -void zend_ffi_expr_is_greater_or_equal(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_is_greater_or_equal(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_cmp(val, op2, >=); } /* }}} */ -void zend_ffi_expr_shift_left(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_shift_left(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, <<); } /* }}} */ -void zend_ffi_expr_shift_right(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_shift_right(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, >>); } /* }}} */ -void zend_ffi_expr_add(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_add(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_math(val, op2, +); } /* }}} */ -void zend_ffi_expr_sub(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_sub(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_math(val, op2, -); } /* }}} */ -void zend_ffi_expr_mul(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_mul(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_math(val, op2, *); } /* }}} */ -void zend_ffi_expr_div(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_div(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_math(val, op2, /); } /* }}} */ -void zend_ffi_expr_mod(zend_ffi_val *val, zend_ffi_val *op2) /* {{{ */ +void zend_ffi_expr_mod(zend_ffi_val *val, const zend_ffi_val *op2) /* {{{ */ { zend_ffi_expr_int_math(val, op2, %); // ??? } @@ -7754,7 +7754,7 @@ void zend_ffi_expr_sizeof_val(zend_ffi_val *val) /* {{{ */ void zend_ffi_expr_sizeof_type(zend_ffi_val *val, zend_ffi_dcl *dcl) /* {{{ */ { - zend_ffi_type *type; + const zend_ffi_type *type; zend_ffi_finalize_type(dcl); type = ZEND_FFI_TYPE(dcl->type); diff --git a/ext/ffi/php_ffi.h b/ext/ffi/php_ffi.h index 430b8a2e568f8..ba92947e62bf4 100644 --- a/ext/ffi/php_ffi.h +++ b/ext/ffi/php_ffi.h @@ -217,45 +217,45 @@ void zend_ffi_resolve_typedef(const char *name, size_t name_len, zend_ffi_dcl *d void zend_ffi_resolve_const(const char *name, size_t name_len, zend_ffi_val *val); void zend_ffi_declare_tag(const char *name, size_t name_len, zend_ffi_dcl *dcl, bool incomplete); void zend_ffi_make_enum_type(zend_ffi_dcl *dcl); -void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name_len, zend_ffi_val *val, int64_t *min, int64_t *max, int64_t *last); +void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name_len, const zend_ffi_val *val, int64_t *min, int64_t *max, int64_t *last); void zend_ffi_make_struct_type(zend_ffi_dcl *dcl); void zend_ffi_add_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl); void zend_ffi_add_anonymous_field(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl); -void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl, zend_ffi_val *bits); +void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl, const zend_ffi_val *bits); void zend_ffi_adjust_struct_size(zend_ffi_dcl *dcl); void zend_ffi_make_pointer_type(zend_ffi_dcl *dcl); -void zend_ffi_make_array_type(zend_ffi_dcl *dcl, zend_ffi_val *len); +void zend_ffi_make_array_type(zend_ffi_dcl *dcl, const zend_ffi_val *len); void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *nested_dcl); void zend_ffi_add_arg(HashTable **args, const char *name, size_t name_len, zend_ffi_dcl *arg_dcl); void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl); void zend_ffi_add_attribute(zend_ffi_dcl *dcl, const char *name, size_t name_len); -void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, zend_ffi_val *val); -void zend_ffi_add_msvc_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, zend_ffi_val *val); +void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, const zend_ffi_val *val); +void zend_ffi_add_msvc_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, const zend_ffi_val *val); void zend_ffi_set_abi(zend_ffi_dcl *dcl, uint16_t abi); void zend_ffi_nested_declaration(zend_ffi_dcl *dcl, zend_ffi_dcl *nested_dcl); void zend_ffi_align_as_type(zend_ffi_dcl *dcl, zend_ffi_dcl *align_dcl); -void zend_ffi_align_as_val(zend_ffi_dcl *dcl, zend_ffi_val *align_val); +void zend_ffi_align_as_val(zend_ffi_dcl *dcl, const zend_ffi_val *align_val); void zend_ffi_validate_type_name(zend_ffi_dcl *dcl); -void zend_ffi_expr_conditional(zend_ffi_val *val, zend_ffi_val *op2, zend_ffi_val *op3); +void zend_ffi_expr_conditional(zend_ffi_val *val, const zend_ffi_val *op2, const zend_ffi_val *op3); void zend_ffi_expr_bool_or(zend_ffi_val *val, zend_ffi_val *op2); void zend_ffi_expr_bool_and(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_bw_or(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_bw_xor(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_bw_and(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_equal(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_not_equal(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_less(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_greater(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_less_or_equal(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_is_greater_or_equal(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_shift_left(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_shift_right(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_add(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_sub(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_mul(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_div(zend_ffi_val *val, zend_ffi_val *op2); -void zend_ffi_expr_mod(zend_ffi_val *val, zend_ffi_val *op2); +void zend_ffi_expr_bw_or(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_bw_xor(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_bw_and(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_equal(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_not_equal(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_less(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_greater(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_less_or_equal(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_is_greater_or_equal(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_shift_left(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_shift_right(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_add(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_sub(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_mul(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_div(zend_ffi_val *val, const zend_ffi_val *op2); +void zend_ffi_expr_mod(zend_ffi_val *val, const zend_ffi_val *op2); void zend_ffi_expr_cast(zend_ffi_val *val, zend_ffi_dcl *dcl); void zend_ffi_expr_plus(zend_ffi_val *val); void zend_ffi_expr_neg(zend_ffi_val *val); From 5a4c46032925ea0cda591a1f2cba3cbc8567753c Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 17:02:59 +0100 Subject: [PATCH 231/503] ext/ffi: Add comment about why a function was manually optimized --- ext/ffi/ffi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index c35dbc52934e4..621e60c6f19a3 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2917,6 +2917,7 @@ static ZEND_FUNCTION(ffi_trampoline) /* {{{ */ } /* }}} */ +/* This function was manually optimized to reduce the overhead of calling native functions */ static zend_function *zend_ffi_get_func(zend_object **obj, zend_string *name, const zval *key) /* {{{ */ { zend_ffi *ffi = (zend_ffi*)*obj; From 9e52d1698a78a7ec4f788c099c79ce642b6aed1e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 20:26:57 +0200 Subject: [PATCH 232/503] Use specialised functions in SplFixedArray dimension handlers This is more efficient than manually dealing with a garbage copy. --- ext/spl/spl_fixedarray.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 99e6983b0ffc0..06b92057fd495 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -377,7 +377,7 @@ static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object * { /* we have to return NULL on error here to avoid memleak because of * ZE duplicating uninitialized_zval_ptr */ - if (!offset) { + if (UNEXPECTED(!offset)) { zend_throw_error(NULL, "[] operator not supported for SplFixedArray"); return NULL; } @@ -422,7 +422,7 @@ static zval *spl_fixedarray_object_read_dimension(zend_object *object, zval *off static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *intern, zval *offset, zval *value) { - if (!offset) { + if (UNEXPECTED(!offset)) { /* '$array[] = value' syntax is not supported */ zend_throw_error(NULL, "[] operator not supported for SplFixedArray"); return; @@ -438,10 +438,10 @@ static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object * } else { /* Fix #81429 */ zval *ptr = &(intern->array.elements[index]); - zval tmp; - ZVAL_COPY_VALUE(&tmp, ptr); - ZVAL_COPY_DEREF(ptr, value); - zval_ptr_dtor(&tmp); + /* This should be guaranteed by the VM handler or argument parsing. */ + ZEND_ASSERT(Z_TYPE_P(value) != IS_REFERENCE); + Z_TRY_ADDREF_P(value); + zend_safe_assign_to_variable_noref(ptr, value); } } @@ -472,10 +472,9 @@ static void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object * if (UNEXPECTED(index >= intern->array.size)) { zend_throw_exception(spl_ce_OutOfBoundsException, "Index invalid or out of range", 0); } else { - zval garbage; - ZVAL_COPY_VALUE(&garbage, &intern->array.elements[index]); - ZVAL_NULL(&intern->array.elements[index]); - zval_ptr_dtor(&garbage); + zval null = {0}; + ZVAL_NULL(&null); + zend_safe_assign_to_variable_noref(&intern->array.elements[index], &null); } } From d20e3e6cb108a11c62f939538369c262e2a51535 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 20:49:13 +0200 Subject: [PATCH 233/503] Simplify handling of inheritance in SplFixedArray After the loop, `parent` will for sure be ce_SplFixedArray, and inherited will be true; for inherited cases. --- ext/spl/spl_fixedarray.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 06b92057fd495..dc32045ba0ff9 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -278,7 +278,6 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z { spl_fixedarray_object *intern; zend_class_entry *parent = class_type; - bool inherited = false; intern = zend_object_alloc(sizeof(spl_fixedarray_object), parent); @@ -290,21 +289,10 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z spl_fixedarray_copy_ctor(&intern->array, &other->array); } - while (parent) { - if (parent == spl_ce_SplFixedArray) { - break; - } - - parent = parent->parent; - inherited = true; - } - - ZEND_ASSERT(parent); - - if (UNEXPECTED(inherited)) { + if (UNEXPECTED(class_type != spl_ce_SplFixedArray)) { /* Find count() method */ zend_function *fptr_count = zend_hash_find_ptr(&class_type->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); - if (fptr_count->common.scope == parent) { + if (fptr_count->common.scope == spl_ce_SplFixedArray) { fptr_count = NULL; } intern->fptr_count = fptr_count; From 355700c9044460967a5974e3b81643588eb9b84d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Wed, 26 Mar 2025 12:17:48 +0100 Subject: [PATCH 234/503] Remove PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK from pcre compile options This option is semi-deprecated [1] and shouldn't influence much anyway. The anticipated BC break is low. [1] https://github.com/PCRE2Project/pcre2/issues/736#issuecomment-2753974366 [2] https://github.com/PCRE2Project/pcre2/issues/736#issuecomment-2754110610 Closes GH-18150. --- NEWS | 2 ++ UPGRADING | 5 +++++ ext/pcre/php_pcre.c | 11 +---------- ext/pcre/tests/bug70345.phpt | 11 ++++++++--- ext/pcre/tests/bug70345_old.phpt | 26 ++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 ext/pcre/tests/bug70345_old.phpt diff --git a/NEWS b/NEWS index dc91f999fb15e..14667511d6651 100644 --- a/NEWS +++ b/NEWS @@ -96,6 +96,8 @@ PHP NEWS - PCRE: . Upgraded to pre2lib from 10.44 to 10.45. (nielsdos) + . Remove PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK from pcre compile options. + (mvorisek) - PDO_PGSQL: . Added Iterable support for PDO::pgsqlCopyFromArray. (KentarouTakeda) diff --git a/UPGRADING b/UPGRADING index 1a525f22f4411..542513a16402b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -59,6 +59,11 @@ PHP 8.5 UPGRADE NOTES . pcntl_exec() now throws ValueErrors when entries or keys of the $env_vars parameter contain null bytes. +- PCRE: + . The extension is compiled without semi-deprecated + PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK compile option. + https://github.com/PCRE2Project/pcre2/issues/736#issuecomment-2754024651 + - PDO: . The constructor arguments set in conjunction with PDO::FETCH_CLASS now follow the usual CUFA (call_user_func_array) semantics. diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index a2a577a6745a0..8e0fb2cce5f9b 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -199,13 +199,6 @@ static void php_pcre_efree(void *block, void *data) efree(block); } -#ifdef PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK - /* pcre 10.38 needs PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK, disabled by default */ -#define PHP_PCRE_DEFAULT_EXTRA_COPTIONS PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK -#else -#define PHP_PCRE_DEFAULT_EXTRA_COPTIONS 0 -#endif - #define PHP_PCRE_PREALLOC_MDATA_SIZE 32 static void php_pcre_init_pcre2(uint8_t jit) @@ -226,8 +219,6 @@ static void php_pcre_init_pcre2(uint8_t jit) } } - pcre2_set_compile_extra_options(cctx, PHP_PCRE_DEFAULT_EXTRA_COPTIONS); - if (!mctx) { mctx = pcre2_match_context_create(gctx); if (!mctx) { @@ -590,7 +581,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, bo #else uint32_t coptions = 0; #endif - uint32_t eoptions = PHP_PCRE_DEFAULT_EXTRA_COPTIONS; + uint32_t eoptions = 0; PCRE2_UCHAR error[128]; PCRE2_SIZE erroffset; int errnumber; diff --git a/ext/pcre/tests/bug70345.phpt b/ext/pcre/tests/bug70345.phpt index 42d4f8b12e265..bdfa2041fc08a 100644 --- a/ext/pcre/tests/bug70345.phpt +++ b/ext/pcre/tests/bug70345.phpt @@ -1,5 +1,10 @@ --TEST-- Bug #70345 (Multiple vulnerabilities related to PCRE functions) +--SKIPIF-- + --EXPECTF-- +Warning: preg_split(): Compilation failed: \K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) at offset 9 in %s on line %d bool(false) -Warning: preg_match(): Get subpatterns list failed in %s on line %d -array(0) { -} +Warning: preg_match(): Compilation failed: \K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) at offset 12 in %s on line %d +NULL diff --git a/ext/pcre/tests/bug70345_old.phpt b/ext/pcre/tests/bug70345_old.phpt new file mode 100644 index 0000000000000..ea455a59330d4 --- /dev/null +++ b/ext/pcre/tests/bug70345_old.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #70345 (Multiple vulnerabilities related to PCRE functions) +--SKIPIF-- += 38) { + die("skip new pcre version"); +} +--FILE-- + +--EXPECTF-- +bool(false) + +Warning: preg_match(): Get subpatterns list failed in %s on line %d +array(0) { +} From aa7c8a9de0ce54bd0d8479b3d64e805843022237 Mon Sep 17 00:00:00 2001 From: William Varmus <0@willvar.tw> Date: Sat, 29 Mar 2025 18:46:08 +0800 Subject: [PATCH 235/503] Address deprecated PHP 8.4 session options to prevent test failures Closes GH-18179. --- NEWS | 4 ++++ build/Makefile.global | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 980cf89ce3bd6..6b344f641681e 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,10 @@ PHP NEWS . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) +- Tests: + . Address deprecated PHP 8.4 session options to prevent test failures. + (willvar) + 10 Apr 2025, PHP 8.4.6 - BCMath: diff --git a/build/Makefile.global b/build/Makefile.global index d5170ebcae4ac..52a629c048a22 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -89,7 +89,7 @@ PHP_TEST_SHARED_EXTENSIONS = ` \ . $$i; $(top_srcdir)/build/shtool echo -n -- " -d zend_extension=$(top_builddir)/modules/$$dlname"; \ done; \ fi` -PHP_DEPRECATED_DIRECTIVES_REGEX = '^(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?)[\t\ ]*=' +PHP_DEPRECATED_DIRECTIVES_REGEX = '^(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?|session\.sid_(length|bits_per_character))[\t\ ]*=' test: all @if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \ From ce3d1cd5cb93e855c6527a475e8e2397fa8cd8cb Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Mon, 31 Mar 2025 11:15:26 -0700 Subject: [PATCH 236/503] Fix typo in `ReflectionParameter::getName()` description [skip ci] --- ext/reflection/php_reflection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5fc4bd6b643b5..b53b7b97c9bc9 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2671,7 +2671,7 @@ ZEND_METHOD(ReflectionParameter, __toString) /* }}} */ -/* {{{ Returns this parameters's name */ +/* {{{ Returns this parameter's name */ ZEND_METHOD(ReflectionParameter, getName) { reflection_object *intern; From a6aacd851b022d46d96110f43072685bacdc5efb Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 28 Mar 2025 14:30:38 +0100 Subject: [PATCH 237/503] Remove static __invoke() handling in zend_std_get_closure() Static __invoke() is disallowed since PHP 8.0. Closes GH-18171 --- Zend/zend_object_handlers.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 076d2b8bbc2dd..5faa7285763ad 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -2451,17 +2451,9 @@ ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **c return FAILURE; } *fptr_ptr = Z_FUNC_P(func); - *ce_ptr = ce; - if ((*fptr_ptr)->common.fn_flags & ZEND_ACC_STATIC) { - if (obj_ptr) { - *obj_ptr = NULL; - } - } else { - if (obj_ptr) { - *obj_ptr = obj; - } - } + *obj_ptr = obj; + return SUCCESS; } /* }}} */ From 13d51f895b44c866858ee31f200f2619f99c731d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:05:07 +0200 Subject: [PATCH 238/503] Add missing EXTENSIONS section to intl test [ci skip] --- ext/intl/tests/dateformat_format_references.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/intl/tests/dateformat_format_references.phpt b/ext/intl/tests/dateformat_format_references.phpt index da1a52955f121..576d901edeb82 100644 --- a/ext/intl/tests/dateformat_format_references.phpt +++ b/ext/intl/tests/dateformat_format_references.phpt @@ -1,5 +1,7 @@ --TEST-- Fix dateformat_format() with array argument with values as references. +--EXTENSIONS-- +intl --SKIPIF-- Date: Tue, 1 Apr 2025 20:51:02 +1000 Subject: [PATCH 239/503] docs: fix spelling in `stubs.rst` (GH-18220) --- docs/source/miscellaneous/stubs.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/miscellaneous/stubs.rst b/docs/source/miscellaneous/stubs.rst index 385eddc5be72f..3899fe3084196 100644 --- a/docs/source/miscellaneous/stubs.rst +++ b/docs/source/miscellaneous/stubs.rst @@ -13,11 +13,11 @@ code, but instead contain empty function and method bodies. A very basic stub lo /** @var float */ const WEIGHT = 6.8; - class Atmopshere { + class Atmosphere { public function calculateBar(): float {} } - function fahrenheitToCelcius(float $fahrenheitToCelcius): float {} + function fahrenheitToCelsius(float $fahrenheitToCelsius): float {} Any kind of symbol can be declared via stubs. Every type can be used, with the exception of disjunctive normal form (DNF) types. Additional meta information can be added via PHPDoc blocks or @@ -33,17 +33,17 @@ using namespace blocks: /** @var float */ const WEIGHT_TON = 6.8; - class Atmopshere { + class Atmosphere { public function calculateBar(): float {} } } namespace Algorithms { - function fahrenheitToCelcius(float $fahrenheit): float {} + function fahrenheitToCelsius(float $fahrenheit): float {} } The above example declares the global constants ``ANIMAL`` and ``WEIGHT_TON``, and the class -``Atmopshere`` in the top-level namespace. The ``fahrenheitToCelcius()`` function is declared to be +``Atmosphere`` in the top-level namespace. The ``fahrenheitToCelsius()`` function is declared to be in the ``Algorithms`` namespace. ******************** @@ -77,11 +77,11 @@ The arginfo file matching our first example looks like: /* This is a generated file, edit the .stub.php file instead. * Stub hash: e4ed788d54a20272a92a3f6618b73d48ec848f97 */ - ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fahrenheitToCelcius, 0, 1, IS_DOUBLE, 0) - ZEND_ARG_TYPE_INFO(0, fahrenheitToCelcius, IS_DOUBLE, 0) + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fahrenheitToCelsius, 0, 1, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, fahrenheitToCelsius, IS_DOUBLE, 0) ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Atmopshere_calculateBar, 0, 0, IS_DOUBLE, 0) + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Atmosphere_calculateBar, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() The hash that is included in the file makes sure that stub files are not reprocessed unless the stub @@ -186,24 +186,24 @@ In order to generate these, add the file-level ``@generate-function-entries`` PH public function calculateBar(): float {} } - function fahrenheitToCelcius(float $fahrenheit): float {} + function fahrenheitToCelsius(float $fahrenheit): float {} Now, the following C code is generated: .. code:: c - ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fahrenheitToCelcius, 0, 1, IS_DOUBLE, 0) + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fahrenheitToCelsius, 0, 1, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, fahrenheit, IS_DOUBLE, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Atmosphere_calculateBar, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() - ZEND_FUNCTION(fahrenheitToCelcius); + ZEND_FUNCTION(fahrenheitToCelsius); ZEND_METHOD(Atmosphere, calculateBar); static const zend_function_entry ext_functions[] = { - ZEND_FE(fahrenheitToCelcius, arginfo_fahrenheitToCelcius) + ZEND_FE(fahrenheitToCelsius, arginfo_fahrenheitToCelsius) ZEND_FE_END }; @@ -762,7 +762,7 @@ Running it with the stub examples that are used in this guide, the following war Warning: Missing class synopsis for Number Warning: Missing class synopsis for Elephant Warning: Missing class synopsis for Atmosphere - Warning: Missing method synopsis for fahrenheitToCelcius() + Warning: Missing method synopsis for fahrenheitToCelsius() Warning: Missing method synopsis for Atmosphere::calculateBar() ********************** From a21065e6ebd4e9aed4e8be05fa691dfa5b0aa41d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 31 Mar 2025 22:06:17 +0200 Subject: [PATCH 240/503] Use-after-free in extract() with EXTR_REFS Fixes GH-18209 Closes GH-18211 --- NEWS | 1 + ext/standard/array.c | 4 +++- ext/standard/tests/gh18209.phpt | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/gh18209.phpt diff --git a/NEWS b/NEWS index c08d732697cb3..37a320d27be07 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) + . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) 10 Apr 2025, PHP 8.3.20 diff --git a/ext/standard/array.c b/ext/standard/array.c index 7382e1e9f8bd9..b89deb241f046 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1863,8 +1863,10 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t } else { ZVAL_MAKE_REF_EX(entry, 2); } - zval_ptr_dtor(orig_var); + zval garbage; + ZVAL_COPY_VALUE(&garbage, orig_var); ZVAL_REF(orig_var, Z_REF_P(entry)); + zval_ptr_dtor(&garbage); } else { if (Z_ISREF_P(entry)) { Z_ADDREF_P(entry); diff --git a/ext/standard/tests/gh18209.phpt b/ext/standard/tests/gh18209.phpt new file mode 100644 index 0000000000000..6a759639f7dcb --- /dev/null +++ b/ext/standard/tests/gh18209.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-18209: Use-after-free in extract() with EXTR_REFS +--CREDITS-- +Noam Rathaus (nrathaus) +--FILE-- + 42]; +extract($array, EXTR_REFS); +var_dump($b); + +?> +--EXPECT-- +int(42) +int(43) From 2ede2009671ba9e73900daf26abdee9e05fe9aab Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 1 Apr 2025 17:11:58 +0200 Subject: [PATCH 241/503] [skip ci] Drop Zend/tests/traits/error_001.phpt The test doesn't test what it says it does. And depending on what it is actually trying to test, it is redundant with either Zend/tests/traits/error_009.phpt, Zend/tests/traits/error_010.phpt or Zend/tests/traits/language015.phpt. --- Zend/tests/traits/error_001.phpt | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 Zend/tests/traits/error_001.phpt diff --git a/Zend/tests/traits/error_001.phpt b/Zend/tests/traits/error_001.phpt deleted file mode 100644 index a7889da41e2b7..0000000000000 --- a/Zend/tests/traits/error_001.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Trying to use instanceof for a method twice ---FILE-- - ---EXPECTF-- -Fatal error: Class A cannot extend trait foo in %s on line %d From 011795bcbebc0d7022d70ded6bf114c3b424ec71 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 13 Sep 2024 17:57:04 +0200 Subject: [PATCH 242/503] Bind traits before parent class This more accurately matches the "copy & paste" semantics described in the documentation. Abstract trait methods diverge from this behavior, given that a parent method can satisfy trait methods used in the child. In that case, the method is not copied, but the check is performed after the parent has been bound. Fixes GH-15753 Fixes GH-16198 Close GH-15878 --- NEWS | 1 + UPGRADING | 3 + Zend/tests/traits/constant_015.phpt | 16 +---- Zend/tests/traits/gh15753.phpt | 23 +++++++ Zend/tests/traits/gh16198.phpt | 36 +++++++++++ Zend/tests/traits/gh16198_2.phpt | 27 ++++++++ Zend/zend_inheritance.c | 99 ++++++++++++++--------------- 7 files changed, 141 insertions(+), 64 deletions(-) create mode 100644 Zend/tests/traits/gh15753.phpt create mode 100644 Zend/tests/traits/gh16198.phpt create mode 100644 Zend/tests/traits/gh16198_2.phpt diff --git a/NEWS b/NEWS index 14667511d6651..1a635fc47cef6 100644 --- a/NEWS +++ b/NEWS @@ -41,6 +41,7 @@ PHP NEWS . Added the (void) cast to indicate that not using a value is intentional. (timwolla) . Added get_error_handler(), get_exception_handler() functions. (Arnaud) + . Fixed bug GH-15753 and GH-16198 (Bind traits before parent class). (ilutov) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/UPGRADING b/UPGRADING index 542513a16402b..791660451359a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -41,6 +41,9 @@ PHP 8.5 UPGRADE NOTES . The tick handlers are now deactivated after all shutdown functions, destructors have run and the output handlers have been cleaned up. This is a consequence of fixing GH-18033. + . Traits are now bound before the parent class. This is a subtle behavioral + change, but should closer match user expectations, demonstrated by GH-15753 + and GH-16198. - Intl: . The extension now requires at least ICU 57.1. diff --git a/Zend/tests/traits/constant_015.phpt b/Zend/tests/traits/constant_015.phpt index 24507ea9e59cd..1b219340506b8 100644 --- a/Zend/tests/traits/constant_015.phpt +++ b/Zend/tests/traits/constant_015.phpt @@ -1,5 +1,5 @@ --TEST-- -The same name constant of a trait used in a class that inherits a constant defined in a parent can be defined only if they are compatible. +Final class constant in parent may not be overridden by child through trait --FILE-- --EXPECTF-- -Fatal error: BaseClass2 and TestTrait2 define the same constant (Constant) in the composition of DerivedClass2. However, the definition differs and is considered incompatible. Class was composed in %s on line %d +Fatal error: DerivedClass1::Constant cannot override final constant BaseClass1::Constant in %s on line %d diff --git a/Zend/tests/traits/gh15753.phpt b/Zend/tests/traits/gh15753.phpt new file mode 100644 index 0000000000000..21e32d96c09e3 --- /dev/null +++ b/Zend/tests/traits/gh15753.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-15753: Trait can override property declared in parent class of used class +--FILE-- +prop); + +?> +--EXPECT-- +int(2) diff --git a/Zend/tests/traits/gh16198.phpt b/Zend/tests/traits/gh16198.phpt new file mode 100644 index 0000000000000..f44926cf5ce24 --- /dev/null +++ b/Zend/tests/traits/gh16198.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-16198: Incorrect trait constant conflict when declared via trait +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/traits/gh16198_2.phpt b/Zend/tests/traits/gh16198_2.phpt new file mode 100644 index 0000000000000..7599ea1a11b49 --- /dev/null +++ b/Zend/tests/traits/gh16198_2.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-16198: Usage of super in cloned trait method +--FILE-- + +--EXPECT-- +string(13) "P::__destruct" diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index bcccf978e2a01..8747e11d151fc 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1135,7 +1135,12 @@ static inheritance_status do_inheritance_check_on_method( #define SEPARATE_METHOD() do { \ if ((flags & ZEND_INHERITANCE_LAZY_CHILD_CLONE) \ - && child_scope != ce && child->type == ZEND_USER_FUNCTION) { \ + && child_scope != ce \ + /* Trait methods have already been separated at this point. However, their */ \ + /* scope isn't fixed until after inheritance checks to preserve the scope */ \ + /* in error messages. Skip them here explicitly. */ \ + && !(child_scope->ce_flags & ZEND_ACC_TRAIT) \ + && child->type == ZEND_USER_FUNCTION) { \ /* op_array wasn't duplicated yet */ \ zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); \ memcpy(new_function, child, sizeof(zend_op_array)); \ @@ -2350,7 +2355,6 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_ { zend_function *existing_fn = NULL; zend_function *new_fn; - bool check_inheritance = false; if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) { /* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless @@ -2384,8 +2388,6 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_ ZSTR_VAL(fn->common.scope->name), ZSTR_VAL(fn->common.function_name), ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(existing_fn->common.scope->name), ZSTR_VAL(existing_fn->common.function_name)); - } else { - check_inheritance = true; } } @@ -2405,19 +2407,6 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_ function_add_ref(new_fn); fn = zend_hash_update_ptr(&ce->function_table, key, new_fn); zend_add_magic_method(ce, fn, key); - - if (check_inheritance) { - /* Inherited members are overridden by members inserted by traits. - * Check whether the trait method fulfills the inheritance requirements. */ - uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY; - if (!(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) { - flags |= ZEND_INHERITANCE_SET_CHILD_CHANGED |ZEND_INHERITANCE_SET_CHILD_PROTO | - ZEND_INHERITANCE_RESET_CHILD_OVERRIDE; - } - do_inheritance_check_on_method( - fn, fixup_trait_scope(fn, ce), existing_fn, fixup_trait_scope(existing_fn, ce), - ce, NULL, flags); - } } /* }}} */ @@ -2695,7 +2684,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e } /* }}} */ -static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases) /* {{{ */ +static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases, bool verify_abstract, bool *contains_abstract_methods) /* {{{ */ { uint32_t i; zend_string *key; @@ -2706,6 +2695,11 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry if (traits[i]) { /* copies functions, applies defined aliasing, and excludes unused trait methods */ ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { + bool is_abstract = (bool) (fn->common.fn_flags & ZEND_ACC_ABSTRACT); + *contains_abstract_methods |= is_abstract; + if (verify_abstract != is_abstract) { + continue; + } zend_traits_copy_functions(key, fn, ce, exclude_tables[i], aliases); } ZEND_HASH_FOREACH_END(); @@ -2720,15 +2714,16 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry for (i = 0; i < ce->num_traits; i++) { if (traits[i]) { ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { + bool is_abstract = (bool) (fn->common.fn_flags & ZEND_ACC_ABSTRACT); + *contains_abstract_methods |= is_abstract; + if (verify_abstract != is_abstract) { + continue; + } zend_traits_copy_functions(key, fn, ce, NULL, aliases); } ZEND_HASH_FOREACH_END(); } } } - - ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { - zend_fixup_trait_method(fn, ce); - } ZEND_HASH_FOREACH_END(); } /* }}} */ @@ -3010,33 +3005,6 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent } /* }}} */ -static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */ -{ - HashTable **exclude_tables; - zend_class_entry **aliases; - - ZEND_ASSERT(ce->num_traits > 0); - - /* complete initialization of trait structures in ce */ - zend_traits_init_trait_structures(ce, traits, &exclude_tables, &aliases); - - /* first care about all methods to be flattened into the class */ - zend_do_traits_method_binding(ce, traits, exclude_tables, aliases); - - if (aliases) { - efree(aliases); - } - - if (exclude_tables) { - efree(exclude_tables); - } - - /* then flatten the constants and properties into it, to, mostly to notify developer about problems */ - zend_do_traits_constant_binding(ce, traits); - zend_do_traits_property_binding(ce, traits); -} -/* }}} */ - #define MAX_ABSTRACT_INFO_CNT 3 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" #define DISPLAY_ABSTRACT_FN(idx) \ @@ -3649,6 +3617,15 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string zend_link_hooked_object_iter(ce); #endif + HashTable **trait_exclude_tables; + zend_class_entry **trait_aliases; + bool trait_contains_abstract_methods = false; + if (ce->num_traits) { + zend_traits_init_trait_structures(ce, traits_and_interfaces, &trait_exclude_tables, &trait_aliases); + zend_do_traits_method_binding(ce, traits_and_interfaces, trait_exclude_tables, trait_aliases, false, &trait_contains_abstract_methods); + zend_do_traits_constant_binding(ce, traits_and_interfaces); + zend_do_traits_property_binding(ce, traits_and_interfaces); + } if (parent) { if (!(parent->ce_flags & ZEND_ACC_LINKED)) { add_dependency_obligation(ce, parent); @@ -3656,7 +3633,29 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string zend_do_inheritance(ce, parent); } if (ce->num_traits) { - zend_do_bind_traits(ce, traits_and_interfaces); + if (trait_contains_abstract_methods) { + zend_do_traits_method_binding(ce, traits_and_interfaces, trait_exclude_tables, trait_aliases, true, &trait_contains_abstract_methods); + } + + if (trait_exclude_tables) { + for (i = 0; i < ce->num_traits; i++) { + if (traits_and_interfaces[i]) { + if (trait_exclude_tables[i]) { + zend_hash_destroy(trait_exclude_tables[i]); + FREE_HASHTABLE(trait_exclude_tables[i]); + } + } + } + efree(trait_exclude_tables); + } + if (trait_aliases) { + efree(trait_aliases); + } + + zend_function *fn; + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { + zend_fixup_trait_method(fn, ce); + } ZEND_HASH_FOREACH_END(); } if (ce->num_interfaces) { /* Also copy the parent interfaces here, so we don't need to reallocate later. */ From 38ecfc54c60fe06c74562e87108a633ec7a39ef6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 15:45:04 +0100 Subject: [PATCH 243/503] ext/filter: Remove dead code about session globals --- ext/filter/filter.c | 9 --------- ext/filter/php_filter.h | 3 --- 2 files changed, 12 deletions(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 9c380163823cd..f7608433bfbe6 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -144,9 +144,6 @@ ZEND_TSRMLS_CACHE_UPDATE(); ZVAL_UNDEF(&filter_globals->cookie_array); ZVAL_UNDEF(&filter_globals->env_array); ZVAL_UNDEF(&filter_globals->server_array); -#if 0 - ZVAL_UNDEF(&filter_globals->session_array); -#endif filter_globals->default_filter = FILTER_DEFAULT; } /* }}} */ @@ -189,9 +186,6 @@ PHP_RSHUTDOWN_FUNCTION(filter) VAR_ARRAY_COPY_DTOR(cookie_array) VAR_ARRAY_COPY_DTOR(server_array) VAR_ARRAY_COPY_DTOR(env_array) -#if 0 - VAR_ARRAY_COPY_DTOR(session_array) -#endif return SUCCESS; } /* }}} */ @@ -234,9 +228,6 @@ static unsigned int php_sapi_filter_init(void) ZVAL_UNDEF(&IF_G(cookie_array)); ZVAL_UNDEF(&IF_G(server_array)); ZVAL_UNDEF(&IF_G(env_array)); -#if 0 - ZVAL_UNDEF(&IF_G(session_array)); -#endif return SUCCESS; } diff --git a/ext/filter/php_filter.h b/ext/filter/php_filter.h index 4587a375e43b8..f782907898fca 100644 --- a/ext/filter/php_filter.h +++ b/ext/filter/php_filter.h @@ -42,9 +42,6 @@ ZEND_BEGIN_MODULE_GLOBALS(filter) zval cookie_array; zval env_array; zval server_array; -#if 0 - zval session_array; -#endif zend_long default_filter; zend_long default_filter_flags; ZEND_END_MODULE_GLOBALS(filter) From 5cbfb6966a328ef523f6ab66ecd49383f0a904a5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 15:47:45 +0100 Subject: [PATCH 244/503] ext/filter: Remove unused parameters --- ext/filter/filter.c | 26 +++++++++++++------------- ext/filter/sanitizing_filters.c | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index f7608433bfbe6..1f60f51372eff 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -231,7 +231,7 @@ static unsigned int php_sapi_filter_init(void) return SUCCESS; } -static void php_zval_filter(zval *value, zend_long filter, zend_long flags, zval *options, char* charset, bool copy) /* {{{ */ +static void php_zval_filter(zval *value, zend_long filter, zend_long flags, zval *options, char* charset) /* {{{ */ { filter_list_entry filter_func; @@ -327,7 +327,7 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t /* Register mangled variable */ if (IF_G(default_filter) != FILTER_UNSAFE_RAW) { ZVAL_STRINGL(&new_var, *val, val_len); - php_zval_filter(&new_var, IF_G(default_filter), IF_G(default_filter_flags), NULL, NULL, 0); + php_zval_filter(&new_var, IF_G(default_filter), IF_G(default_filter_flags), NULL, NULL); } else { ZVAL_STRINGL(&new_var, *val, val_len); } @@ -356,7 +356,7 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t } /* }}} */ -static void php_zval_filter_recursive(zval *value, zend_long filter, zend_long flags, zval *options, char *charset, bool copy) /* {{{ */ +static void php_zval_filter_recursive(zval *value, zend_long filter, zend_long flags, zval *options, char *charset) /* {{{ */ { if (Z_TYPE_P(value) == IS_ARRAY) { zval *element; @@ -370,14 +370,14 @@ static void php_zval_filter_recursive(zval *value, zend_long filter, zend_long f ZVAL_DEREF(element); if (Z_TYPE_P(element) == IS_ARRAY) { SEPARATE_ARRAY(element); - php_zval_filter_recursive(element, filter, flags, options, charset, copy); + php_zval_filter_recursive(element, filter, flags, options, charset); } else { - php_zval_filter(element, filter, flags, options, charset, copy); + php_zval_filter(element, filter, flags, options, charset); } } ZEND_HASH_FOREACH_END(); Z_UNPROTECT_RECURSION_P(value); } else { - php_zval_filter(value, filter, flags, options, charset, copy); + php_zval_filter(value, filter, flags, options, charset); } } /* }}} */ @@ -449,7 +449,7 @@ PHP_FUNCTION(filter_has_var) static void php_filter_call( zval *filtered, zend_long filter, HashTable *filter_args_ht, zend_long filter_args_long, - const int copy, zend_long filter_flags + zend_long filter_flags ) /* {{{ */ { zval *options = NULL; zval *option; @@ -501,7 +501,7 @@ static void php_filter_call( } return; } - php_zval_filter_recursive(filtered, filter, filter_flags, options, charset, copy); + php_zval_filter_recursive(filtered, filter, filter_flags, options, charset); return; } if (filter_flags & FILTER_REQUIRE_ARRAY) { @@ -514,7 +514,7 @@ static void php_filter_call( return; } - php_zval_filter(filtered, filter, filter_flags, options, charset, copy); + php_zval_filter(filtered, filter, filter_flags, options, charset); if (filter_flags & FILTER_FORCE_ARRAY) { zval tmp; ZVAL_COPY_VALUE(&tmp, filtered); @@ -532,7 +532,7 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op if (!op_ht) { ZVAL_DUP(return_value, input); - php_filter_call(return_value, -1, NULL, op_long, 0, FILTER_REQUIRE_ARRAY); + php_filter_call(return_value, -1, NULL, op_long, FILTER_REQUIRE_ARRAY); } else { array_init(return_value); @@ -556,7 +556,7 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op php_filter_call(&nval, -1, Z_TYPE_P(arg_elm) == IS_ARRAY ? Z_ARRVAL_P(arg_elm) : NULL, Z_TYPE_P(arg_elm) == IS_ARRAY ? 0 : zval_get_long(arg_elm), - 0, FILTER_REQUIRE_SCALAR + FILTER_REQUIRE_SCALAR ); zend_hash_update(Z_ARRVAL_P(return_value), arg_key, &nval); } @@ -625,7 +625,7 @@ PHP_FUNCTION(filter_input) ZVAL_DUP(return_value, tmp); - php_filter_call(return_value, filter, filter_args_ht, filter_args_long, 1, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR); } /* }}} */ @@ -651,7 +651,7 @@ PHP_FUNCTION(filter_var) ZVAL_DUP(return_value, data); - php_filter_call(return_value, filter, filter_args_ht, filter_args_long, 1, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR); } /* }}} */ diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index 647d559c1df56..21024a99a0f31 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -60,7 +60,7 @@ static const unsigned char hexchars[] = "0123456789ABCDEF"; #define DEFAULT_URL_ENCODE LOWALPHA HIALPHA DIGIT "-._" -static void php_filter_encode_url(http://github.com/zval%20*value,%20const%20unsigned%20char*%20chars,%20const%20int%20char_len,%20int%20high,%20int%20low,%20int%20encode_nul) +static void php_filter_encode_url(http://github.com/zval%20*value,%20const%20unsigned%20char*%20chars,%20const%20int%20char_len) { unsigned char *p; unsigned char tmp[256]; @@ -216,7 +216,7 @@ void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL) /* apply strip_high and strip_low filters */ php_filter_strip(value, flags); /* urlencode */ - php_filter_encode_url(http://github.com/value,%20(unsigned%20char%20*)DEFAULT_URL_ENCODE, sizeof(DEFAULT_URL_ENCODE)-1, flags & FILTER_FLAG_ENCODE_HIGH, flags & FILTER_FLAG_ENCODE_LOW, 1); + php_filter_encode_url(http://github.com/value,%20(unsigned%20char%20*)DEFAULT_URL_ENCODE, sizeof(DEFAULT_URL_ENCODE)-1); } /* }}} */ From 53bced39fbd5ec2580ec0d0495d679bea2ec0906 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 15:54:25 +0100 Subject: [PATCH 245/503] ext/filter: Reduce scope of variables --- ext/filter/filter.c | 21 ++++++++++----------- ext/filter/logical_filters.c | 6 +++--- ext/filter/sanitizing_filters.c | 3 +-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 1f60f51372eff..50eefb440d67a 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -100,9 +100,9 @@ ZEND_GET_MODULE(filter) static PHP_INI_MH(UpdateDefaultFilter) /* {{{ */ { - int i, size = sizeof(filter_list) / sizeof(filter_list_entry); + int size = sizeof(filter_list) / sizeof(filter_list_entry); - for (i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { if ((strcasecmp(ZSTR_VAL(new_value), filter_list[i].name) == 0)) { IF_G(default_filter) = filter_list[i].id; if (IF_G(default_filter) != FILTER_DEFAULT) { @@ -452,7 +452,6 @@ static void php_filter_call( zend_long filter_flags ) /* {{{ */ { zval *options = NULL; - zval *option; char *charset = NULL; if (!filter_args_ht) { @@ -467,6 +466,7 @@ static void php_filter_call( filter = filter_args_long; } } else { + zval *option; if ((option = zend_hash_str_find(filter_args_ht, "filter", sizeof("filter") - 1)) != NULL) { filter = zval_get_long(option); } @@ -527,14 +527,13 @@ static void php_filter_call( static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op_long, zval *return_value, bool add_empty ) /* {{{ */ { - zend_string *arg_key; - zval *tmp, *arg_elm; - if (!op_ht) { ZVAL_DUP(return_value, input); php_filter_call(return_value, -1, NULL, op_long, FILTER_REQUIRE_ARRAY); } else { array_init(return_value); + zend_string *arg_key; + zval *arg_elm; ZEND_HASH_FOREACH_STR_KEY_VAL(op_ht, arg_key, arg_elm) { if (arg_key == NULL) { @@ -545,6 +544,7 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op zend_argument_value_error(2, "cannot contain empty keys"); RETURN_THROWS(); } + zval *tmp; if ((tmp = zend_hash_find(Z_ARRVAL_P(input), arg_key)) == NULL) { if (add_empty) { add_assoc_null_ex(return_value, ZSTR_VAL(arg_key), ZSTR_LEN(arg_key)); @@ -594,10 +594,10 @@ PHP_FUNCTION(filter_input) if (!input || (tmp = zend_hash_find(Z_ARRVAL_P(input), var)) == NULL) { zend_long filter_flags = 0; - zval *option, *opt, *def; if (!filter_args_ht) { filter_flags = filter_args_long; } else { + zval *option, *opt, *def; if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { filter_flags = zval_get_long(option); } @@ -717,14 +717,14 @@ PHP_FUNCTION(filter_var_array) /* {{{ Returns a list of all supported filters */ PHP_FUNCTION(filter_list) { - int i, size = sizeof(filter_list) / sizeof(filter_list_entry); + int size = sizeof(filter_list) / sizeof(filter_list_entry); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } array_init(return_value); - for (i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { add_next_index_string(return_value, (char *)filter_list[i].name); } } @@ -733,7 +733,6 @@ PHP_FUNCTION(filter_list) /* {{{ Returns the filter ID belonging to a named filter */ PHP_FUNCTION(filter_id) { - int i; size_t filter_len; int size = sizeof(filter_list) / sizeof(filter_list_entry); char *filter; @@ -742,7 +741,7 @@ PHP_FUNCTION(filter_id) RETURN_THROWS(); } - for (i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { if (strcmp(filter_list[i].name, filter) == 0) { RETURN_LONG(filter_list[i].id); } diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index d0d60c00ebc63..7a718131a48e4 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -1037,7 +1037,7 @@ void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { char *input = Z_STRVAL_P(value); size_t input_len = Z_STRLEN_P(value); - int tokens, length, i, offset, exp_separator_set; + int tokens, length, exp_separator_set; size_t exp_separator_len; char separator; char *exp_separator; @@ -1080,8 +1080,8 @@ void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ * a hexadecimal number followed by a separator character. (With the * exception of the last token which does not have the separator.) */ - for (i = 0; i < tokens; i++) { - offset = i * (length + 1); + for (int i = 0; i < tokens; i++) { + int offset = i * (length + 1); if (i < tokens - 1 && input[offset + length] != separator) { /* The current token did not end with e.g. a "." */ diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index 21024a99a0f31..9d4cc1660e66d 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -98,7 +98,6 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const static void php_filter_strip(zval *value, zend_long flags) { unsigned char *str; - size_t i; size_t c; zend_string *buf; @@ -110,7 +109,7 @@ static void php_filter_strip(zval *value, zend_long flags) str = (unsigned char *)Z_STRVAL_P(value); buf = zend_string_alloc(Z_STRLEN_P(value), 0); c = 0; - for (i = 0; i < Z_STRLEN_P(value); i++) { + for (size_t i = 0; i < Z_STRLEN_P(value); i++) { if ((str[i] >= 127) && (flags & FILTER_FLAG_STRIP_HIGH)) { } else if ((str[i] < 32) && (flags & FILTER_FLAG_STRIP_LOW)) { } else if ((str[i] == '`') && (flags & FILTER_FLAG_STRIP_BACKTICK)) { From 0e682ad6926f3b9bc10166293ab252c02b1639df Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 16:05:05 +0100 Subject: [PATCH 246/503] ext/filter: Add const qualifiers --- ext/filter/logical_filters.c | 18 +++++++++--------- ext/filter/sanitizing_filters.c | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 7a718131a48e4..7dc57c5d7b028 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -203,7 +203,7 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ size_t len; int error = 0; zend_long ctx_value; - char *p; + const char *p; /* Parse options */ FETCH_LONG_OPTION(min_range, "min_range"); @@ -272,7 +272,7 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - char *str = Z_STRVAL_P(value); + const char *str = Z_STRVAL_P(value); size_t len = Z_STRLEN_P(value); int ret; @@ -342,7 +342,7 @@ void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { size_t len; - char *str, *end; + const char *str, *end; char *num, *p; zval *option_val; char *decimal; @@ -504,9 +504,9 @@ void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } } -static int _php_filter_validate_domain(char * domain, size_t len, zend_long flags) /* {{{ */ +static int _php_filter_validate_domain(const char *domain, size_t len, zend_long flags) /* {{{ */ { - char *e, *s, *t; + const char *e, *s, *t; size_t l; int hostname = flags & FILTER_FLAG_HOSTNAME; unsigned char i = 1; @@ -564,7 +564,7 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* }}} */ -static int is_userinfo_valid(zend_string *str) +static int is_userinfo_valid(const zend_string *str) { const char *valid = "-._~!$&'()*+,;=:"; const char *p = ZSTR_VAL(str); @@ -723,7 +723,7 @@ void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* }}} */ -static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{ */ +static int _php_filter_validate_ipv4(const char *str, size_t str_len, int *ip) /* {{{ */ { const char *end = str + str_len; int num, m; @@ -763,7 +763,7 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) int compressed_pos = -1; int blocks = 0; int num, n, i; - char *ipv4; + const char *ipv4; const char *end; int ip4elm[4]; const char *s = str; @@ -1035,7 +1035,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - char *input = Z_STRVAL_P(value); + const char *input = Z_STRVAL_P(value); size_t input_len = Z_STRLEN_P(value); int tokens, length, exp_separator_set; size_t exp_separator_len; diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index 9d4cc1660e66d..7f8b4948d5818 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -64,8 +64,8 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const { unsigned char *p; unsigned char tmp[256]; - unsigned char *s = (unsigned char *)chars; - unsigned char *e = s + char_len; + const unsigned char *s = chars; + const unsigned char *e = s + char_len; zend_string *str; memset(tmp, 1, sizeof(tmp)-1); @@ -75,8 +75,8 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const } str = zend_string_safe_alloc(Z_STRLEN_P(value), 3, 0, 0); - p = (unsigned char *) ZSTR_VAL(str); - s = (unsigned char *) Z_STRVAL_P(value); + p = (unsigned char*)ZSTR_VAL(str); + s = (const unsigned char*)Z_STRVAL_P(value); e = s + Z_STRLEN_P(value); while (s < e) { @@ -90,14 +90,14 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const s++; } *p = '\0'; - ZSTR_LEN(str) = p - (unsigned char *)ZSTR_VAL(str); + ZSTR_LEN(str) = p - (const unsigned char *)ZSTR_VAL(str); zval_ptr_dtor(value); ZVAL_NEW_STR(value, str); } static void php_filter_strip(zval *value, zend_long flags) { - unsigned char *str; + const unsigned char *str; size_t c; zend_string *buf; @@ -106,7 +106,7 @@ static void php_filter_strip(zval *value, zend_long flags) return; } - str = (unsigned char *)Z_STRVAL_P(value); + str = (const unsigned char *)Z_STRVAL_P(value); buf = zend_string_alloc(Z_STRLEN_P(value), 0); c = 0; for (size_t i = 0; i < Z_STRLEN_P(value); i++) { @@ -142,9 +142,9 @@ static void filter_map_update(filter_map *map, int flag, const unsigned char *al } } -static void filter_map_apply(zval *value, filter_map *map) +static void filter_map_apply(zval *value, const filter_map *map) { - unsigned char *str; + const unsigned char *str; size_t i, c; zend_string *buf; From 7cc47082d64c0dedf8e8de85b314e92f1dcee9f3 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 16:25:59 +0100 Subject: [PATCH 247/503] ext/filter: Use zend_string* instead of a char* + size_t pair --- ext/filter/logical_filters.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 7dc57c5d7b028..1937521e14def 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -504,16 +504,16 @@ void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } } -static int _php_filter_validate_domain(const char *domain, size_t len, zend_long flags) /* {{{ */ +static int php_filter_validate_domain_ex(const zend_string *domain, zend_long flags) /* {{{ */ { const char *e, *s, *t; size_t l; int hostname = flags & FILTER_FLAG_HOSTNAME; unsigned char i = 1; - s = domain; - l = len; - e = domain + l; + s = ZSTR_VAL(domain); + l = ZSTR_LEN(domain); + e = s + l; t = e - 1; /* Ignore trailing dot */ @@ -558,7 +558,7 @@ static int _php_filter_validate_domain(const char *domain, size_t len, zend_long void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - if (!_php_filter_validate_domain(Z_STRVAL_P(value), Z_STRLEN_P(value), flags)) { + if (!php_filter_validate_domain_ex(Z_STR_P(value), flags)) { RETURN_VALIDATION_FAILED } } @@ -580,12 +580,12 @@ static int is_userinfo_valid(const zend_string *str) return 1; } -static bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l) +static bool php_filter_is_valid_ipv6_hostname(const zend_string *s) { - const char *e = s + l; + const char *e = ZSTR_VAL(s) + ZSTR_LEN(s); const char *t = e - 1; - return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2, NULL); + return *ZSTR_VAL(s) == '[' && *t == ']' && _php_filter_validate_ipv6(ZSTR_VAL(s) + 1, ZSTR_LEN(s) - 2, NULL); } void php_filter_validate_url(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ @@ -608,22 +608,17 @@ void php_filter_validate_url(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (url->scheme != NULL && (zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) { - const char *s; - size_t l; if (url->host == NULL) { goto bad_url; } - s = ZSTR_VAL(url->host); - l = ZSTR_LEN(url->host); - if ( /* An IPv6 enclosed by square brackets is a valid hostname.*/ - !php_filter_is_valid_ipv6_hostname(s, l) && + !php_filter_is_valid_ipv6_hostname(url->host) && /* Validate domain. * This includes a loose check for an IPv4 address. */ - !_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME) + !php_filter_validate_domain_ex(url->host, FILTER_FLAG_HOSTNAME) ) { php_url_free(url); RETURN_VALIDATION_FAILED From fa511dff459ce0f7ce48d74d7a0b9f01f2db5c1f Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 16:26:29 +0100 Subject: [PATCH 248/503] ext/filter: Mark literal as static const --- ext/filter/logical_filters.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 1937521e14def..c6171e70a2b34 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -566,9 +566,9 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ static int is_userinfo_valid(const zend_string *str) { - const char *valid = "-._~!$&'()*+,;=:"; const char *p = ZSTR_VAL(str); while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) { + static const char *valid = "-._~!$&'()*+,;=:"; if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) { p++; } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) { From f11c22ae305eb757b1ffabd145c466f61dd5e9ea Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 31 Mar 2025 16:13:25 +0100 Subject: [PATCH 249/503] ext/filter: Use bool instead of int where applicable This makes it easier to reason about the code --- ext/filter/logical_filters.c | 123 ++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index c6171e70a2b34..054b0ed9d6430 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -89,16 +89,17 @@ #define FORMAT_IPV4 4 #define FORMAT_IPV6 6 -static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]); +static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]); -static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ +static bool php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ zend_long ctx_value; - int sign = 0, digit = 0; + bool is_negative = false; + int digit = 0; const char *end = str + str_len; switch (*str) { case '-': - sign = 1; + is_negative = true; ZEND_FALLTHROUGH; case '+': str++; @@ -108,43 +109,43 @@ static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) if (*str == '0' && str + 1 == end) { /* Special cases: +0 and -0 */ - return 1; + return true; } /* must start with 1..9*/ if (str < end && *str >= '1' && *str <= '9') { - ctx_value = ((sign)?-1:1) * ((*(str++)) - '0'); + ctx_value = (is_negative?-1:1) * ((*(str++)) - '0'); } else { - return -1; + return false; } if ((end - str > MAX_LENGTH_OF_LONG - 1) /* number too long */ || (SIZEOF_LONG == 4 && (end - str == MAX_LENGTH_OF_LONG - 1) && *str > '2')) { /* overflow */ - return -1; + return false; } while (str < end) { if (*str >= '0' && *str <= '9') { digit = (*(str++) - '0'); - if ( (!sign) && ctx_value <= (ZEND_LONG_MAX-digit)/10 ) { + if ( (!is_negative) && ctx_value <= (ZEND_LONG_MAX-digit)/10 ) { ctx_value = (ctx_value * 10) + digit; - } else if ( sign && ctx_value >= (ZEND_LONG_MIN+digit)/10) { + } else if ( is_negative && ctx_value >= (ZEND_LONG_MIN+digit)/10) { ctx_value = (ctx_value * 10) - digit; } else { - return -1; + return false; } } else { - return -1; + return false; } } *ret = ctx_value; - return 1; + return true; } /* }}} */ -static int php_filter_parse_octal(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ +static bool php_filter_parse_octal(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ zend_ulong ctx_value = 0; const char *end = str + str_len; @@ -154,20 +155,20 @@ static int php_filter_parse_octal(const char *str, size_t str_len, zend_long *re if ((ctx_value > ((zend_ulong)(~(zend_long)0)) / 8) || ((ctx_value = ctx_value * 8) > ((zend_ulong)(~(zend_long)0)) - n)) { - return -1; + return false; } ctx_value += n; } else { - return -1; + return false; } } *ret = (zend_long)ctx_value; - return 1; + return true; } /* }}} */ -static int php_filter_parse_hex(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ +static bool php_filter_parse_hex(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ zend_ulong ctx_value = 0; const char *end = str + str_len; zend_ulong n; @@ -180,17 +181,17 @@ static int php_filter_parse_hex(const char *str, size_t str_len, zend_long *ret) } else if (*str >= 'A' && *str <= 'F') { n = ((*(str++)) - ('A' - 10)); } else { - return -1; + return false; } if ((ctx_value > ((zend_ulong)(~(zend_long)0)) / 16) || ((ctx_value = ctx_value * 16) > ((zend_ulong)(~(zend_long)0)) - n)) { - return -1; + return false; } ctx_value += n; } *ret = (zend_long)ctx_value; - return 1; + return true; } /* }}} */ @@ -199,9 +200,9 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ zval *option_val; zend_long min_range, max_range, option_flags; int min_range_set, max_range_set; - int allow_octal = 0, allow_hex = 0; + bool allow_octal = false, allow_hex = false; size_t len; - int error = 0; + bool error = false; zend_long ctx_value; const char *p; @@ -217,11 +218,11 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } if (option_flags & FILTER_FLAG_ALLOW_OCTAL) { - allow_octal = 1; + allow_octal = true; } if (option_flags & FILTER_FLAG_ALLOW_HEX) { - allow_hex = 1; + allow_hex = true; } /* Start the validating loop */ @@ -237,8 +238,8 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (len == 0) { RETURN_VALIDATION_FAILED } - if (php_filter_parse_hex(p, len, &ctx_value) < 0) { - error = 1; + if (!php_filter_parse_hex(p, len, &ctx_value)) { + error = true; } } else if (allow_octal) { /* Support explicit octal prefix notation */ @@ -248,19 +249,19 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } } - if (php_filter_parse_octal(p, len, &ctx_value) < 0) { - error = 1; + if (!php_filter_parse_octal(p, len, &ctx_value)) { + error = true; } } else if (len != 0) { - error = 1; + error = true; } } else { - if (php_filter_parse_int(p, len, &ctx_value) < 0) { - error = 1; + if (!php_filter_parse_int(p, len, &ctx_value)) { + error = true; } } - if (error > 0 || (min_range_set && (ctx_value < min_range)) || (max_range_set && (ctx_value > max_range))) { + if (error || (min_range_set && (ctx_value < min_range)) || (max_range_set && (ctx_value > max_range))) { RETURN_VALIDATION_FAILED } else { zval_ptr_dtor(value); @@ -359,7 +360,7 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ double min_range, max_range; int min_range_set, max_range_set; - int first, n; + int n; len = Z_STRLEN_P(value); str = Z_STRVAL_P(value); @@ -398,7 +399,7 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (str < end && (*str == '+' || *str == '-')) { *p++ = *str++; } - first = 1; + bool first = true; while (1) { n = 0; while (str < end && *str >= '0' && *str <= '9') { @@ -431,7 +432,7 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (first?(n < 1 || n > 3):(n != 3)) { goto error; } - first = 0; + first = false; str++; } else { goto error; @@ -504,7 +505,7 @@ void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } } -static int php_filter_validate_domain_ex(const zend_string *domain, zend_long flags) /* {{{ */ +static bool php_filter_validate_domain_ex(const zend_string *domain, zend_long flags) /* {{{ */ { const char *e, *s, *t; size_t l; @@ -524,26 +525,26 @@ static int php_filter_validate_domain_ex(const zend_string *domain, zend_long fl /* The total length cannot exceed 253 characters (final dot not included) */ if (l > 253) { - return 0; + return false; } /* First char must be alphanumeric */ if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) { - return 0; + return false; } while (s < e) { if (*s == '.') { /* The first and the last character of a label must be alphanumeric */ if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) { - return 0; + return false; } /* Reset label length counter */ i = 1; } else { if (i > 63 || (hostname && (*s != '-' || *(s + 1) == '\0') && !isalnum((int)*(unsigned char *)s))) { - return 0; + return false; } i++; @@ -552,7 +553,7 @@ static int php_filter_validate_domain_ex(const zend_string *domain, zend_long fl s++; } - return 1; + return true; } /* }}} */ @@ -564,7 +565,7 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* }}} */ -static int is_userinfo_valid(const zend_string *str) +static bool is_userinfo_valid(const zend_string *str) { const char *p = ZSTR_VAL(str); while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) { @@ -574,10 +575,10 @@ static int is_userinfo_valid(const zend_string *str) } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) { p += 3; } else { - return 0; + return false; } } - return 1; + return true; } static bool php_filter_is_valid_ipv6_hostname(const zend_string *s) @@ -718,16 +719,16 @@ void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* }}} */ -static int _php_filter_validate_ipv4(const char *str, size_t str_len, int *ip) /* {{{ */ +static bool _php_filter_validate_ipv4(const char *str, size_t str_len, int *ip) /* {{{ */ { const char *end = str + str_len; int num, m; int n = 0; while (str < end) { - int leading_zero; + bool leading_zero; if (*str < '0' || *str > '9') { - return 0; + return false; } leading_zero = (*str == '0'); m = 1; @@ -735,25 +736,25 @@ static int _php_filter_validate_ipv4(const char *str, size_t str_len, int *ip) / while (str < end && (*str >= '0' && *str <= '9')) { num = num * 10 + ((*(str++)) - '0'); if (num > 255 || ++m > 3) { - return 0; + return false; } } /* don't allow a leading 0; that introduces octal numbers, * which we don't support */ if (leading_zero && (num != 0 || m > 1)) - return 0; + return false; ip[n++] = num; if (n == 4) { return str == end; } else if (str >= end || *(str++) != '.') { - return 0; + return false; } } - return 0; + return false; } /* }}} */ -static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) /* {{{ */ +static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) /* {{{ */ { int compressed_pos = -1; int blocks = 0; @@ -797,11 +798,11 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) if (*str == ':') { if (++str >= end) { /* cannot end in : without previous : */ - return 0; + return false; } if (*str == ':') { if (compressed_pos >= 0) { - return 0; + return false; } if (ip && blocks < 8) { ip[blocks] = -1; @@ -809,13 +810,13 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) compressed_pos = blocks++; /* :: means 1 or more 16-bit 0 blocks */ if (++str == end) { if (blocks > 8) { - return 0; + return false; } goto fixup_ip; } } else if ((str - 1) == s) { /* don't allow leading : without another : following */ - return 0; + return false; } } num = n = 0; @@ -836,10 +837,10 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) ip[blocks] = num; } if (n < 1 || n > 4) { - return 0; + return false; } if (++blocks > 8) - return 0; + return false; } fixup_ip: @@ -1005,7 +1006,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } } else if (mode == FORMAT_IPV6) { - if (_php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value), ip) < 1) { + if (!_php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value), ip)) { RETURN_VALIDATION_FAILED } @@ -1082,7 +1083,7 @@ void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ /* The current token did not end with e.g. a "." */ RETURN_VALIDATION_FAILED } - if (php_filter_parse_hex(input + offset, length, &ret) < 0) { + if (!php_filter_parse_hex(input + offset, length, &ret)) { /* The current token is no valid hexadecimal digit */ RETURN_VALIDATION_FAILED } From 5544be7018fe64584945c49fffcda20402bece73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 2 Apr 2025 09:35:29 +0200 Subject: [PATCH 250/503] RFC: Marking return values as important (#[\NoDiscard]) (#17599) RFC: https://wiki.php.net/rfc/marking_return_value_as_important Co-authored-by: Volker Dusch --- NEWS | 4 +- UPGRADING | 9 +- Zend/Optimizer/optimize_func_calls.c | 20 ++-- Zend/tests/attributes/nodiscard/001.phpt | 86 +++++++++++++++ Zend/tests/attributes/nodiscard/002.phpt | 44 ++++++++ Zend/tests/attributes/nodiscard/003.phpt | 22 ++++ Zend/tests/attributes/nodiscard/005.phpt | 17 +++ Zend/tests/attributes/nodiscard/006.phpt | 20 ++++ Zend/tests/attributes/nodiscard/007.phpt | 21 ++++ Zend/tests/attributes/nodiscard/008.phpt | 18 ++++ Zend/tests/attributes/nodiscard/009.phpt | 14 +++ Zend/tests/attributes/nodiscard/010.phpt | 76 +++++++++++++ .../attributes/nodiscard/error_code_001.phpt | 21 ++++ .../nodiscard/property_readonly_001.phpt | 14 +++ .../nodiscard/property_readonly_002.phpt | 15 +++ .../attributes/nodiscard/suppress_assign.phpt | 66 ++++++++++++ .../attributes/nodiscard/suppress_cast.phpt | 66 ++++++++++++ .../nodiscard/throwing_error_handler_001.phpt | 35 ++++++ .../nodiscard/type_validation_001.phpt | 15 +++ .../nodiscard/type_validation_002.phpt | 20 ++++ .../nodiscard/type_validation_003.phpt | 18 ++++ .../nodiscard/type_validation_004.phpt | 18 ++++ .../nodiscard/unsupported_clone.phpt | 16 +++ .../nodiscard/unsupported_constructor.phpt | 16 +++ .../nodiscard/unsupported_never_function.phpt | 15 +++ .../unsupported_property_hook_get.phpt | 20 ++++ .../unsupported_property_hook_set.phpt | 20 ++++ .../nodiscard/unsupported_void_function.phpt | 15 +++ Zend/zend_API.c | 10 ++ Zend/zend_attributes.c | 27 +++++ Zend/zend_attributes.h | 1 + Zend/zend_attributes.stub.php | 11 ++ Zend/zend_attributes_arginfo.h | 33 +++++- Zend/zend_compile.c | 52 ++++++++- Zend/zend_compile.h | 7 +- Zend/zend_execute.c | 81 ++++++++++++++ Zend/zend_execute.h | 1 + Zend/zend_object_handlers.c | 2 +- Zend/zend_vm_def.h | 22 +++- Zend/zend_vm_execute.h | 66 +++++++++--- build/gen_stub.php | 10 +- ext/date/php_date.stub.php | 9 ++ ext/date/php_date_arginfo.h | 102 ++++++++++++++++-- ext/opcache/jit/zend_jit_internal.h | 2 + ext/opcache/jit/zend_jit_ir.c | 42 +++++--- ext/opcache/jit/zend_jit_vm_helpers.c | 48 +++++++++ ext/standard/basic_functions.stub.php | 1 + ext/standard/basic_functions_arginfo.h | 13 ++- ext/standard/tests/file/userstreams_004.phpt | 2 +- ext/zend_test/test.c | 7 ++ ext/zend_test/test.stub.php | 5 + ext/zend_test/test_arginfo.h | 34 +++++- 52 files changed, 1261 insertions(+), 68 deletions(-) create mode 100644 Zend/tests/attributes/nodiscard/001.phpt create mode 100644 Zend/tests/attributes/nodiscard/002.phpt create mode 100644 Zend/tests/attributes/nodiscard/003.phpt create mode 100644 Zend/tests/attributes/nodiscard/005.phpt create mode 100644 Zend/tests/attributes/nodiscard/006.phpt create mode 100644 Zend/tests/attributes/nodiscard/007.phpt create mode 100644 Zend/tests/attributes/nodiscard/008.phpt create mode 100644 Zend/tests/attributes/nodiscard/009.phpt create mode 100644 Zend/tests/attributes/nodiscard/010.phpt create mode 100644 Zend/tests/attributes/nodiscard/error_code_001.phpt create mode 100644 Zend/tests/attributes/nodiscard/property_readonly_001.phpt create mode 100644 Zend/tests/attributes/nodiscard/property_readonly_002.phpt create mode 100644 Zend/tests/attributes/nodiscard/suppress_assign.phpt create mode 100644 Zend/tests/attributes/nodiscard/suppress_cast.phpt create mode 100644 Zend/tests/attributes/nodiscard/throwing_error_handler_001.phpt create mode 100644 Zend/tests/attributes/nodiscard/type_validation_001.phpt create mode 100644 Zend/tests/attributes/nodiscard/type_validation_002.phpt create mode 100644 Zend/tests/attributes/nodiscard/type_validation_003.phpt create mode 100644 Zend/tests/attributes/nodiscard/type_validation_004.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_clone.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_constructor.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_never_function.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_property_hook_get.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_property_hook_set.phpt create mode 100644 Zend/tests/attributes/nodiscard/unsupported_void_function.phpt diff --git a/NEWS b/NEWS index 1a635fc47cef6..65cebd217e130 100644 --- a/NEWS +++ b/NEWS @@ -38,8 +38,10 @@ PHP NEWS . Fixed bug GH-18033 (NULL-ptr dereference when using register_tick_function in destructor). (nielsdos) . Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov) + . Added the #[\NoDiscard] attribute to indicate that a function's return + value is important and should be consumed. (timwolla, Volker Dusch) . Added the (void) cast to indicate that not using a value is intentional. - (timwolla) + (timwolla, Volker Dusch) . Added get_error_handler(), get_exception_handler() functions. (Arnaud) . Fixed bug GH-15753 and GH-16198 (Bind traits before parent class). (ilutov) diff --git a/UPGRADING b/UPGRADING index 791660451359a..c8d45b54544d6 100644 --- a/UPGRADING +++ b/UPGRADING @@ -114,8 +114,13 @@ PHP 8.5 UPGRADE NOTES . Fatal Errors (such as an exceeded maximum execution time) now include a backtrace. RFC: https://wiki.php.net/rfc/error_backtraces_v2 - . Added the (void) to indicate that not using a value is intentional. The - (void) cast does nothing by itself. + . Added the #[\NoDiscard] attribute to indicate that a function's return + value is important and should be consumed. + RFC: https://wiki.php.net/rfc/marking_return_value_as_important + . Added the (void) cast to indicate that not using a value is intentional. + The (void) cast has no effect on the program's execution by itself, but + it can be used to suppress warnings emitted by #[\NoDiscard] and possibly + also diagnostics emitted by external IDEs or static analysis tools. RFC: https://wiki.php.net/rfc/marking_return_value_as_important - Curl: diff --git a/Zend/Optimizer/optimize_func_calls.c b/Zend/Optimizer/optimize_func_calls.c index ce6c43afaedbe..8b29f47c94976 100644 --- a/Zend/Optimizer/optimize_func_calls.c +++ b/Zend/Optimizer/optimize_func_calls.c @@ -78,8 +78,10 @@ static void zend_delete_call_instructions(zend_op_array *op_array, zend_op *opli static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_op *opline, zend_function *func) { + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + if (func->type == ZEND_USER_FUNCTION - && !(func->op_array.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_DEPRECATED)) + && !(func->op_array.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_DEPRECATED|no_discard)) /* TODO: function copied from trait may be inconsistent ??? */ && !(func->op_array.fn_flags & (ZEND_ACC_TRAIT_CLONE)) && fcall->extended_value >= func->op_array.required_num_args @@ -202,18 +204,12 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&ZEND_OP2_LITERAL(fcall)); fcall->op2.constant = fcall->op2.constant + 1; - if (opline->opcode != ZEND_CALLABLE_CONVERT) { - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); - } } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant + 2]); fcall->op2.constant = fcall->op2.constant + 1; - if (opline->opcode != ZEND_CALLABLE_CONVERT) { - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); - } } else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL || fcall->opcode == ZEND_INIT_METHOD_CALL || fcall->opcode == ZEND_INIT_PARENT_PROPERTY_HOOK_CALL @@ -223,6 +219,16 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) ZEND_UNREACHABLE(); } + /* If the INIT opcode changed the DO opcode can also change to + * a more optimized one. + * + * At this point we also know whether or not the result of + * the DO opcode is used, allowing to optimize calls to + * ZEND_ACC_NODISCARD functions. */ + if (opline->opcode != ZEND_CALLABLE_CONVERT) { + opline->opcode = zend_get_call_op(fcall, call_stack[call].func, !RESULT_UNUSED(opline)); + } + if ((ZEND_OPTIMIZER_PASS_16 & ctx->optimization_level) && call_stack[call].try_inline && opline->opcode != ZEND_CALLABLE_CONVERT) { diff --git a/Zend/tests/attributes/nodiscard/001.phpt b/Zend/tests/attributes/nodiscard/001.phpt new file mode 100644 index 0000000000000..8bec9972aed67 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/001.phpt @@ -0,0 +1,86 @@ +--TEST-- +#[\NoDiscard]: Basic test. +--FILE-- +test(); +$cls->test2(); +Clazz::test3(); + +call_user_func([$cls, "test"]); + +$closure(); + +$closure2(); + +?> +--EXPECTF-- +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function test2() should either be used or intentionally ignored by casting it as (void), this is important in %s on line %d + +Warning: The return value of function test3() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of method Clazz::test() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of method Clazz::test2() should either be used or intentionally ignored by casting it as (void), this is important in %s on line %d + +Warning: The return value of method Clazz::test3() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of method Clazz::test() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function {closure:%s:%d}() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function {closure:%s:%d}() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/002.phpt b/Zend/tests/attributes/nodiscard/002.phpt new file mode 100644 index 0000000000000..618aa2f6286d6 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/002.phpt @@ -0,0 +1,44 @@ +--TEST-- +#[\NoDiscard]: __call(), __callStatic(), and __invoke(). +--FILE-- +test(); +Clazz::test(); +$cls('foo'); + +?> +--EXPECTF-- +Warning: The return value of method Clazz::test() should either be used or intentionally ignored by casting it as (void) in %s on line %d +__call(test) + +Warning: The return value of method Clazz::test() should either be used or intentionally ignored by casting it as (void) in %s on line %d +__callStatic(test) + +Warning: The return value of method Clazz::__invoke() should either be used or intentionally ignored by casting it as (void) in %s on line %d +__invoke(foo) + diff --git a/Zend/tests/attributes/nodiscard/003.phpt b/Zend/tests/attributes/nodiscard/003.phpt new file mode 100644 index 0000000000000..24865f350472c --- /dev/null +++ b/Zend/tests/attributes/nodiscard/003.phpt @@ -0,0 +1,22 @@ +--TEST-- +#[\NoDiscard]: Taken from trait. +--FILE-- +test(); + +?> +--EXPECTF-- +Warning: The return value of method Clazz::test() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/005.phpt b/Zend/tests/attributes/nodiscard/005.phpt new file mode 100644 index 0000000000000..ec8f33e5299d6 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/005.phpt @@ -0,0 +1,17 @@ +--TEST-- +#[\NoDiscard]: Native function and method. +--FILE-- +setTimestamp(0); + +?> +--EXPECTF-- +Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d + +Warning: The return value of method DateTimeImmutable::setTimestamp() should either be used or intentionally ignored by casting it as (void), as DateTimeImmutable::setTimestamp() does not modify the object itself in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/006.phpt b/Zend/tests/attributes/nodiscard/006.phpt new file mode 100644 index 0000000000000..959b942522204 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/006.phpt @@ -0,0 +1,20 @@ +--TEST-- +#[\NoDiscard]: execute_ex overwritten +--EXTENSIONS-- +zend_test +--INI-- +zend_test.replace_zend_execute_ex=1 +opcache.jit=disable +--FILE-- + +--EXPECTF-- +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/007.phpt b/Zend/tests/attributes/nodiscard/007.phpt new file mode 100644 index 0000000000000..84dff0c8e44f6 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/007.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\NoDiscard]: execute_internal overwritten +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.execute_internal=1 +--FILE-- + +--EXPECTF-- + + + +Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d + + diff --git a/Zend/tests/attributes/nodiscard/008.phpt b/Zend/tests/attributes/nodiscard/008.phpt new file mode 100644 index 0000000000000..6b4635e08d562 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/008.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\NoDiscard]: Combining with #[\Deprecated]. +--FILE-- + +--EXPECTF-- +Deprecated: Function test() is deprecated in %s on line %d + +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/009.phpt b/Zend/tests/attributes/nodiscard/009.phpt new file mode 100644 index 0000000000000..ab887db7a14b0 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/009.phpt @@ -0,0 +1,14 @@ +--TEST-- +#[\NoDiscard]: Combining with #[\Deprecated] (Internal). +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Deprecated: Function zend_test_deprecated_nodiscard() is deprecated, custom message in %s on line %d + +Warning: The return value of function zend_test_deprecated_nodiscard() should either be used or intentionally ignored by casting it as (void), custom message 2 in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/010.phpt b/Zend/tests/attributes/nodiscard/010.phpt new file mode 100644 index 0000000000000..2de81d76aa6ae --- /dev/null +++ b/Zend/tests/attributes/nodiscard/010.phpt @@ -0,0 +1,76 @@ +--TEST-- +#[\NoDiscard]: Functions with known-used result use DO_[IU]CALL opcodes +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=29, args=0, vars=3, tmps=1) + ; (after optimizer) + ; %s +0000 INIT_FCALL 0 %d string("tmpfile") +0001 V3 = DO_ICALL +0002 ASSIGN CV0($f) V3 +0003 INIT_FCALL 2 %d string("flock") +0004 SEND_VAR CV0($f) 1 +0005 SEND_VAL int(5) 2 +0006 DO_FCALL_BY_NAME +0007 INIT_FCALL 2 %d string("flock") +0008 SEND_VAR CV0($f) 1 +0009 SEND_VAL int(5) 2 +0010 V3 = DO_ICALL +0011 FREE V3 +0012 INIT_FCALL 2 %d string("flock") +0013 SEND_VAR CV0($f) 1 +0014 SEND_VAL int(5) 2 +0015 V3 = DO_ICALL +0016 ASSIGN CV1($success) V3 +0017 INIT_FCALL 1 %d string("fclose") +0018 SEND_VAR CV0($f) 1 +0019 DO_ICALL +0020 INIT_FCALL 0 %d string("test") +0021 DO_FCALL_BY_NAME +0022 INIT_FCALL 0 %d string("test") +0023 V3 = DO_UCALL +0024 FREE V3 +0025 INIT_FCALL 0 %d string("test") +0026 V3 = DO_UCALL +0027 ASSIGN CV2($obj) V3 +0028 RETURN int(1) + +test: + ; (lines=3, args=0, vars=0, tmps=1) + ; (after optimizer) + ; %s +0000 V0 = NEW 0 string("stdClass") +0001 DO_FCALL +0002 RETURN V0 +LIVE RANGES: + 0: 0001 - 0002 (new) + +Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d + +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/error_code_001.phpt b/Zend/tests/attributes/nodiscard/error_code_001.phpt new file mode 100644 index 0000000000000..2952587db7b87 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/error_code_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\NoDiscard]: Code is E_USER_WARNING. +--FILE-- + +--EXPECT-- +int(512) +int(512) +bool(true) diff --git a/Zend/tests/attributes/nodiscard/property_readonly_001.phpt b/Zend/tests/attributes/nodiscard/property_readonly_001.phpt new file mode 100644 index 0000000000000..6f9779023126e --- /dev/null +++ b/Zend/tests/attributes/nodiscard/property_readonly_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +#[\NoDiscard]: NoDiscard::$message is readonly. +--FILE-- +message = 'bar'; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot modify readonly property NoDiscard::$message in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/property_readonly_002.phpt b/Zend/tests/attributes/nodiscard/property_readonly_002.phpt new file mode 100644 index 0000000000000..f01594ca4b26c --- /dev/null +++ b/Zend/tests/attributes/nodiscard/property_readonly_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\NoDiscard]: __construct() respects that properties are readonly. +--FILE-- +__construct("bar"); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot modify readonly property NoDiscard::$message in %s:%d +Stack trace: +#0 %s(%d): NoDiscard->__construct('bar') +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/suppress_assign.phpt b/Zend/tests/attributes/nodiscard/suppress_assign.phpt new file mode 100644 index 0000000000000..b09f1a39718a8 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/suppress_assign.phpt @@ -0,0 +1,66 @@ +--TEST-- +#[\NoDiscard]: Assigning to variable suppresses. +--FILE-- +test(); +$_ = $cls->test2(); +$_ = call_user_func([$cls, "test"]); +$_ = Clazz::test3(); + +$_ = $closure(); + +$_ = $closure2(); + +?> +DONE +--EXPECT-- +DONE diff --git a/Zend/tests/attributes/nodiscard/suppress_cast.phpt b/Zend/tests/attributes/nodiscard/suppress_cast.phpt new file mode 100644 index 0000000000000..2f639371cb3dd --- /dev/null +++ b/Zend/tests/attributes/nodiscard/suppress_cast.phpt @@ -0,0 +1,66 @@ +--TEST-- +#[\NoDiscard]: Casting to (void) suppresses. +--FILE-- +test(); +(void)$cls->test2(); +(void)call_user_func([$cls, "test"]); +(void)Clazz::test3(); + +(void)$closure(); + +(void)$closure2(); + +?> +DONE +--EXPECT-- +DONE diff --git a/Zend/tests/attributes/nodiscard/throwing_error_handler_001.phpt b/Zend/tests/attributes/nodiscard/throwing_error_handler_001.phpt new file mode 100644 index 0000000000000..51179b26ab194 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/throwing_error_handler_001.phpt @@ -0,0 +1,35 @@ +--TEST-- +#[\NoDiscard]: Throwing error handler. +--FILE-- +getMessage(), PHP_EOL; +} + +#[\NoDiscard] +function test2(): stdClass { + return new stdClass(); +} + +try { + test2(); +} catch (ErrorException $e) { + echo "Caught: ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Caught: The return value of function test() should either be used or intentionally ignored by casting it as (void) +Caught: The return value of function test2() should either be used or intentionally ignored by casting it as (void) diff --git a/Zend/tests/attributes/nodiscard/type_validation_001.phpt b/Zend/tests/attributes/nodiscard/type_validation_001.phpt new file mode 100644 index 0000000000000..b7a375ada5c07 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/type_validation_001.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\NoDiscard]: Type validation of $message parameter with int. +--FILE-- + +--EXPECTF-- +Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void), 1234 in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/type_validation_002.phpt b/Zend/tests/attributes/nodiscard/type_validation_002.phpt new file mode 100644 index 0000000000000..254fae15ac47a --- /dev/null +++ b/Zend/tests/attributes/nodiscard/type_validation_002.phpt @@ -0,0 +1,20 @@ +--TEST-- +#[\NoDiscard]: Type validation of $message parameter with int and strict types. +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: NoDiscard::__construct(): Argument #1 ($message) must be of type ?string, int given in %s:%d +Stack trace: +#0 %s(%d): NoDiscard->__construct(1234) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/type_validation_003.phpt b/Zend/tests/attributes/nodiscard/type_validation_003.phpt new file mode 100644 index 0000000000000..0b66addaea187 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/type_validation_003.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\NoDiscard]: Type validation of $message parameter with array. +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: NoDiscard::__construct(): Argument #1 ($message) must be of type ?string, array given in %s:%d +Stack trace: +#0 %s(%d): NoDiscard->__construct(Array) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/type_validation_004.phpt b/Zend/tests/attributes/nodiscard/type_validation_004.phpt new file mode 100644 index 0000000000000..44d7c19b54863 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/type_validation_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\NoDiscard]: Type validation of $message parameter with native enum case. +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: NoDiscard::__construct(): Argument #1 ($message) must be of type ?string, Random\IntervalBoundary given in %s:%d +Stack trace: +#0 %s(%d): NoDiscard->__construct(Random\IntervalBoundary::ClosedOpen) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_clone.phpt b/Zend/tests/attributes/nodiscard/unsupported_clone.phpt new file mode 100644 index 0000000000000..7fadfea40fa6a --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_clone.phpt @@ -0,0 +1,16 @@ +--TEST-- +#[\NoDiscard]: Not allowed on '__clone'. +--FILE-- + +--EXPECTF-- +Fatal error: Method Clazz::__clone cannot be #[\NoDiscard] in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_constructor.phpt b/Zend/tests/attributes/nodiscard/unsupported_constructor.phpt new file mode 100644 index 0000000000000..a11c6379938d3 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_constructor.phpt @@ -0,0 +1,16 @@ +--TEST-- +#[\NoDiscard]: Not allowed on '__construct'. +--FILE-- + +--EXPECTF-- +Fatal error: Method Clazz::__construct cannot be #[\NoDiscard] in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_never_function.phpt b/Zend/tests/attributes/nodiscard/unsupported_never_function.phpt new file mode 100644 index 0000000000000..ee7a81acbcde9 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_never_function.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\NoDiscard]: Not allowed on never function. +--FILE-- + +--EXPECTF-- +Fatal error: A never returning function does not return a value, but #[\NoDiscard] requires a return value in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_property_hook_get.phpt b/Zend/tests/attributes/nodiscard/unsupported_property_hook_get.phpt new file mode 100644 index 0000000000000..ccedf3ede315a --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_property_hook_get.phpt @@ -0,0 +1,20 @@ +--TEST-- +#[\NoDiscard]: Not allowed on 'get' property hook. +--FILE-- +test; + +?> +--EXPECTF-- +Fatal error: #[\NoDiscard] is not supported for property hooks in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_property_hook_set.phpt b/Zend/tests/attributes/nodiscard/unsupported_property_hook_set.phpt new file mode 100644 index 0000000000000..351593f5250bb --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_property_hook_set.phpt @@ -0,0 +1,20 @@ +--TEST-- +#[\NoDiscard]: Not allowed on 'set' property hook. +--FILE-- +test = $value; + } + } +} + +$cls = new Foo(); +$cls->test = 'foo'; + +?> +--EXPECTF-- +Fatal error: #[\NoDiscard] is not supported for property hooks in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/unsupported_void_function.phpt b/Zend/tests/attributes/nodiscard/unsupported_void_function.phpt new file mode 100644 index 0000000000000..3c45f255473bc --- /dev/null +++ b/Zend/tests/attributes/nodiscard/unsupported_void_function.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\NoDiscard]: Not allowed on void function. +--FILE-- + +--EXPECTF-- +Fatal error: A void function does not return a value, but #[\NoDiscard] requires a return value in %s on line %d diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5bc4b4a04509f..4c31fba5e506e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2698,6 +2698,12 @@ static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_ static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type) { + if (return_type == MAY_BE_VOID) { + if (fptr->common.fn_flags & ZEND_ACC_NODISCARD) { + zend_error_noreturn(error_type, "Method %s::%s cannot be #[\\NoDiscard]", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name)); + } + } + if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { /* For backwards compatibility reasons, do not enforce the return type if it is not set. */ return; @@ -2757,6 +2763,10 @@ static void zend_check_magic_method_no_return_type( zend_error_noreturn(error_type, "Method %s::%s() cannot declare a return type", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name)); } + + if (fptr->common.fn_flags & ZEND_ACC_NODISCARD) { + zend_error_noreturn(error_type, "Method %s::%s cannot be #[\\NoDiscard]", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name)); + } } ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */ diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index d7bcb1f54e889..48f79c12610f6 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -31,6 +31,7 @@ ZEND_API zend_class_entry *zend_ce_sensitive_parameter; ZEND_API zend_class_entry *zend_ce_sensitive_parameter_value; ZEND_API zend_class_entry *zend_ce_override; ZEND_API zend_class_entry *zend_ce_deprecated; +ZEND_API zend_class_entry *zend_ce_nodiscard; static zend_object_handlers attributes_object_handlers_sensitive_parameter_value; @@ -193,6 +194,29 @@ ZEND_METHOD(Deprecated, __construct) } } +ZEND_METHOD(NoDiscard, __construct) +{ + zend_string *message = NULL; + zval value; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(message) + ZEND_PARSE_PARAMETERS_END(); + + if (message) { + ZVAL_STR(&value, message); + } else { + ZVAL_NULL(&value); + } + zend_update_property_ex(zend_ce_nodiscard, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_MESSAGE), &value); + + /* The assignment might fail due to 'readonly'. */ + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } +} + static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset) { if (attributes) { @@ -520,6 +544,9 @@ void zend_register_attribute_ce(void) zend_ce_deprecated = register_class_Deprecated(); attr = zend_mark_internal_attribute(zend_ce_deprecated); + + zend_ce_nodiscard = register_class_NoDiscard(); + attr = zend_mark_internal_attribute(zend_ce_nodiscard); } void zend_attributes_shutdown(void) diff --git a/Zend/zend_attributes.h b/Zend/zend_attributes.h index 8a825247c00f8..468488800ebf8 100644 --- a/Zend/zend_attributes.h +++ b/Zend/zend_attributes.h @@ -47,6 +47,7 @@ extern ZEND_API zend_class_entry *zend_ce_sensitive_parameter; extern ZEND_API zend_class_entry *zend_ce_sensitive_parameter_value; extern ZEND_API zend_class_entry *zend_ce_override; extern ZEND_API zend_class_entry *zend_ce_deprecated; +extern ZEND_API zend_class_entry *zend_ce_nodiscard; typedef struct { zend_string *name; diff --git a/Zend/zend_attributes.stub.php b/Zend/zend_attributes.stub.php index 0a35b0c57cb44..6351ccd771838 100644 --- a/Zend/zend_attributes.stub.php +++ b/Zend/zend_attributes.stub.php @@ -84,3 +84,14 @@ final class Deprecated public function __construct(?string $message = null, ?string $since = null) {} } + +/** + * @strict-properties + */ +#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION)] +final class NoDiscard +{ + public readonly ?string $message; + + public function __construct(?string $message = null) {} +} diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index 018caa47d0ac5..aecb216291071 100644 --- a/Zend/zend_attributes_arginfo.h +++ b/Zend/zend_attributes_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2358a0d820edd06a1702c84104bfd545af08311c */ + * Stub hash: 6b54bc195be211caabb395b621380681953c1f5a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL") @@ -29,6 +29,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Deprecated___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, since, IS_STRING, 1, "null") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NoDiscard___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, message, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() + ZEND_METHOD(Attribute, __construct); ZEND_METHOD(ReturnTypeWillChange, __construct); ZEND_METHOD(AllowDynamicProperties, __construct); @@ -38,6 +42,7 @@ ZEND_METHOD(SensitiveParameterValue, getValue); ZEND_METHOD(SensitiveParameterValue, __debugInfo); ZEND_METHOD(Override, __construct); ZEND_METHOD(Deprecated, __construct); +ZEND_METHOD(NoDiscard, __construct); static const zend_function_entry class_Attribute_methods[] = { ZEND_ME(Attribute, __construct, arginfo_class_Attribute___construct, ZEND_ACC_PUBLIC) @@ -76,6 +81,11 @@ static const zend_function_entry class_Deprecated_methods[] = { ZEND_FE_END }; +static const zend_function_entry class_NoDiscard_methods[] = { + ZEND_ME(NoDiscard, __construct, arginfo_class_NoDiscard___construct, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + static zend_class_entry *register_class_Attribute(void) { zend_class_entry ce, *class_entry; @@ -253,3 +263,24 @@ static zend_class_entry *register_class_Deprecated(void) return class_entry; } + +static zend_class_entry *register_class_NoDiscard(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "NoDiscard", class_NoDiscard_methods); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES); + + zval property_message_default_value; + ZVAL_UNDEF(&property_message_default_value); + zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_MESSAGE), &property_message_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); + + zend_string *attribute_name_Attribute_class_NoDiscard_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_NoDiscard_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_NoDiscard_0, 1); + zend_string_release(attribute_name_Attribute_class_NoDiscard_0); + zval attribute_Attribute_class_NoDiscard_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_NoDiscard_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION); + ZVAL_COPY_VALUE(&attribute_Attribute_class_NoDiscard_0->args[0].value, &attribute_Attribute_class_NoDiscard_0_arg0); + + return class_entry; +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8e4221673c4cf..c1988fdaa1535 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3927,13 +3927,15 @@ static uint32_t zend_compile_args( } /* }}} */ -ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* {{{ */ +ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used) /* {{{ */ { - if (fbc) { + uint32_t no_discard = result_used ? 0 : ZEND_ACC_NODISCARD; + + if (fbc && init_op->opcode != ZEND_NEW) { ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)); if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) { if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) { - if (!(fbc->common.fn_flags & ZEND_ACC_DEPRECATED)) { + if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { return ZEND_DO_ICALL; } else { return ZEND_DO_FCALL_BY_NAME; @@ -3941,7 +3943,7 @@ ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* } } else if (!(CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)){ if (zend_execute_ex == execute_ex) { - if (!(fbc->common.fn_flags & ZEND_ACC_DEPRECATED)) { + if (!(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { return ZEND_DO_UCALL; } else { return ZEND_DO_FCALL_BY_NAME; @@ -3991,7 +3993,16 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc); } - opline = zend_emit_op(result, zend_get_call_op(opline, fbc), NULL, NULL); + uint8_t call_op = zend_get_call_op( + opline, + fbc, + /* result_used: At this point we do not yet reliably + * know if the result is used. Deoptimize #[\NoDiscard] + * calls to be sure. The optimizer will fix this up. + */ + false + ); + opline = zend_emit_op(result, call_op, NULL, NULL); if (may_have_extra_named_args) { opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; } @@ -8353,6 +8364,16 @@ static zend_op_array *zend_compile_func_decl_ex( if (deprecated_attribute) { op_array->fn_flags |= ZEND_ACC_DEPRECATED; } + + zend_attribute *nodiscard_attribute = zend_get_attribute_str( + op_array->attributes, + "nodiscard", + sizeof("nodiscard")-1 + ); + + if (nodiscard_attribute) { + op_array->fn_flags |= ZEND_ACC_NODISCARD; + } } /* Do not leak the class scope into free standing functions, even if they are dynamically @@ -8403,6 +8424,27 @@ static zend_op_array *zend_compile_func_decl_ex( } } + if (op_array->fn_flags & ZEND_ACC_NODISCARD) { + if (is_hook) { + zend_error_noreturn(E_COMPILE_ERROR, "#[\\NoDiscard] is not supported for property hooks"); + } + + if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; + if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_VOID)) { + zend_error_noreturn(E_COMPILE_ERROR, + "A void %s does not return a value, but #[\\NoDiscard] requires a return value", + CG(active_class_entry) != NULL ? "method" : "function"); + } + + if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER)) { + zend_error_noreturn(E_COMPILE_ERROR, + "A never returning %s does not return a value, but #[\\NoDiscard] requires a return value", + CG(active_class_entry) != NULL ? "method" : "function"); + } + } + } + zend_compile_stmt(stmt_ast); if (is_method) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 224a68be749cb..db087bdd60035 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -333,7 +333,7 @@ typedef struct _zend_oparray_context { /* Class cannot be serialized or unserialized | | | */ #define ZEND_ACC_NOT_SERIALIZABLE (1 << 29) /* X | | | */ /* | | | */ -/* Function Flags (unused: 29-30) | | | */ +/* Function Flags (unused: 30) | | | */ /* ============== | | | */ /* | | | */ /* deprecation flag | | | */ @@ -395,6 +395,9 @@ typedef struct _zend_oparray_context { /* has #[\Override] attribute | | | */ #define ZEND_ACC_OVERRIDE (1 << 28) /* | X | | */ /* | | | */ +/* has #[\NoDiscard] attribute | | | */ +#define ZEND_ACC_NODISCARD (1 << 29) /* | X | | */ +/* | | | */ /* op_array uses strict mode types | | | */ #define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */ @@ -981,7 +984,7 @@ ZEND_API bool zend_is_compiling(void); ZEND_API char *zend_make_compiled_string_description(const char *name); ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers); uint32_t zend_get_class_fetch_type(const zend_string *name); -ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc); +ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used); ZEND_API bool zend_is_smart_branch(const zend_op *opline); typedef bool (*zend_auto_global_callback)(zend_string *name); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 6b6af2c225f79..e7f7d19118d3b 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1907,6 +1907,87 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_functi zend_string_release(message_suffix); } +ZEND_COLD static zend_result ZEND_FASTCALL get_nodiscard_suffix_from_attribute(HashTable *attributes, zend_class_entry* scope, zend_string **message_suffix) +{ + *message_suffix = ZSTR_EMPTY_ALLOC(); + + if (!attributes) { + return SUCCESS; + } + + zend_attribute *nodiscard = zend_get_attribute_str(attributes, "nodiscard", sizeof("nodiscard")-1); + + if (!nodiscard) { + return SUCCESS; + } + + if (nodiscard->argc == 0) { + return SUCCESS; + } + + zend_result result = FAILURE; + + zend_string *message = ZSTR_EMPTY_ALLOC(); + + zval obj; + ZVAL_UNDEF(&obj); + zval *z; + + /* Construct the NoDiscard object to correctly handle parameter processing. */ + if (FAILURE == zend_get_attribute_object(&obj, zend_ce_nodiscard, nodiscard, scope, NULL)) { + goto out; + } + + /* Extract the $message property. */ + z = zend_read_property_ex(zend_ce_nodiscard, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL); + ZEND_ASSERT(z != &EG(uninitialized_zval)); + if (Z_TYPE_P(z) == IS_STRING) { + message = Z_STR_P(z); + } + + /* Construct the suffix. */ + *message_suffix = zend_strpprintf_unchecked( + 0, + "%s%S", + ZSTR_LEN(message) > 0 ? ", " : "", + message + ); + + result = SUCCESS; + + out: + + zval_ptr_dtor(&obj); + + return result; +} + +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc) +{ + zend_string *message_suffix = ZSTR_EMPTY_ALLOC(); + + if (get_nodiscard_suffix_from_attribute(fbc->common.attributes, fbc->common.scope, &message_suffix) == FAILURE) { + return; + } + + int code = fbc->type == ZEND_INTERNAL_FUNCTION ? E_WARNING : E_USER_WARNING; + + if (fbc->common.scope) { + zend_error_unchecked(code, "The return value of method %s::%s() should either be used or intentionally ignored by casting it as (void)%S", + ZSTR_VAL(fbc->common.scope->name), + ZSTR_VAL(fbc->common.function_name), + message_suffix + ); + } else { + zend_error_unchecked(code, "The return value of function %s() should either be used or intentionally ignored by casting it as (void)%S", + ZSTR_VAL(fbc->common.function_name), + message_suffix + ); + } + + zend_string_release(message_suffix); +} + ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name) { zend_string *message_suffix = ZSTR_EMPTY_ALLOC(); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 3b8ed89ec4f38..e96a217a2904f 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -62,6 +62,7 @@ extern ZEND_API const zend_internal_function zend_pass_function; ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void); ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 5faa7285763ad..a31c7d2afdeee 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1679,7 +1679,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC | ZEND_ACC_VARIADIC - | (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)); + | (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD)); /* Attributes outlive the trampoline because they are created by the compiler. */ func->attributes = fbc->common.attributes; if (is_static) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6c87b81bc3bd7..563928c9dbf59 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4156,8 +4156,15 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); if (!RETURN_VALUE_USED(opline)) { @@ -4260,8 +4267,15 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 06b4ad6b1494a..97466dab76a94 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1552,8 +1552,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = 0 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); if (!0) { @@ -1654,8 +1661,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = 1 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); if (!1) { @@ -1756,8 +1770,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_ SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); if (!RETURN_VALUE_USED(opline)) { @@ -1860,8 +1881,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = 0 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); @@ -1978,8 +2006,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = 1 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); @@ -2096,8 +2131,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_deprecated_function(fbc); + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); diff --git a/build/gen_stub.php b/build/gen_stub.php index f8e16064ee292..e69846733a9d9 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1519,9 +1519,13 @@ private function getArginfoFlagsByPhpVersions(): array } foreach ($this->attributes as $attr) { - if ($attr->class === "Deprecated") { - $flags[] = "ZEND_ACC_DEPRECATED"; - break; + switch ($attr->class) { + case "Deprecated": + $flags[] = "ZEND_ACC_DEPRECATED"; + break; + case "NoDiscard": + $flags[] = "ZEND_ACC_NODISCARD"; + break; } } diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index d0119aac88ad5..f375c60ff0a4c 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -524,29 +524,38 @@ public function getMicrosecond(): int {} public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::modify() does not modify the object itself")] public function modify(string $modifier): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::add() does not modify the object itself")] public function add(DateInterval $interval): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::sub() does not modify the object itself")] public function sub(DateInterval $interval): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::setTimezone() does not modify the object itself")] public function setTimezone(DateTimeZone $timezone): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::setTime() does not modify the object itself")] public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::setDate() does not modify the object itself")] public function setDate(int $year, int $month, int $day): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::setISODate() does not modify the object itself")] public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTimeImmutable {} /** @tentative-return-type */ + #[\NoDiscard(message: "as DateTimeImmutable::setTimestamp() does not modify the object itself")] public function setTimestamp(int $timestamp): DateTimeImmutable {} + #[\NoDiscard(message: "as DateTimeImmutable::setMicrosecond() does not modify the object itself")] public function setMicrosecond(int $microsecond): static {} /** @tentative-return-type */ diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 8ce0114206cfe..82e9f0f1718ae 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d7a318f6fd85e23c6352323e03c323035a511738 */ + * Stub hash: 093743b4fe7a698d1262cc1a81b60a85064fdccb */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0) @@ -725,15 +725,15 @@ static const zend_function_entry class_DateTimeImmutable_methods[] = { ZEND_RAW_FENTRY("getTimestamp", zif_date_timestamp_get, arginfo_class_DateTimeImmutable_getTimestamp, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getMicrosecond", zim_DateTime_getMicrosecond, arginfo_class_DateTimeImmutable_getMicrosecond, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("diff", zif_date_diff, arginfo_class_DateTimeImmutable_diff, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_ME(DateTimeImmutable, modify, arginfo_class_DateTimeImmutable_modify, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, add, arginfo_class_DateTimeImmutable_add, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, sub, arginfo_class_DateTimeImmutable_sub, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setTimezone, arginfo_class_DateTimeImmutable_setTimezone, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setTime, arginfo_class_DateTimeImmutable_setTime, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setDate, arginfo_class_DateTimeImmutable_setDate, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setISODate, arginfo_class_DateTimeImmutable_setISODate, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setTimestamp, arginfo_class_DateTimeImmutable_setTimestamp, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, setMicrosecond, arginfo_class_DateTimeImmutable_setMicrosecond, ZEND_ACC_PUBLIC) + ZEND_ME(DateTimeImmutable, modify, arginfo_class_DateTimeImmutable_modify, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, add, arginfo_class_DateTimeImmutable_add, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, sub, arginfo_class_DateTimeImmutable_sub, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setTimezone, arginfo_class_DateTimeImmutable_setTimezone, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setTime, arginfo_class_DateTimeImmutable_setTime, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setDate, arginfo_class_DateTimeImmutable_setDate, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setISODate, arginfo_class_DateTimeImmutable_setISODate, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setTimestamp, arginfo_class_DateTimeImmutable_setTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) + ZEND_ME(DateTimeImmutable, setMicrosecond, arginfo_class_DateTimeImmutable_setMicrosecond, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) ZEND_ME(DateTimeImmutable, createFromMutable, arginfo_class_DateTimeImmutable_createFromMutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DateTimeImmutable, createFromInterface, arginfo_class_DateTimeImmutable_createFromInterface, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END @@ -989,6 +989,88 @@ static zend_class_entry *register_class_DateTimeImmutable(zend_class_entry *clas class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0); zend_class_implements(class_entry, 1, class_entry_DateTimeInterface); + + zend_string *attribute_name_NoDiscard_func_modify_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_modify_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "modify", sizeof("modify") - 1), attribute_name_NoDiscard_func_modify_0, 1); + zend_string_release(attribute_name_NoDiscard_func_modify_0); + zval attribute_NoDiscard_func_modify_0_arg0; + zend_string *attribute_NoDiscard_func_modify_0_arg0_str = zend_string_init("as DateTimeImmutable::modify() does not modify the object itself", strlen("as DateTimeImmutable::modify() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_modify_0_arg0, attribute_NoDiscard_func_modify_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_modify_0->args[0].value, &attribute_NoDiscard_func_modify_0_arg0); + attribute_NoDiscard_func_modify_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_add_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_add_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "add", sizeof("add") - 1), attribute_name_NoDiscard_func_add_0, 1); + zend_string_release(attribute_name_NoDiscard_func_add_0); + zval attribute_NoDiscard_func_add_0_arg0; + zend_string *attribute_NoDiscard_func_add_0_arg0_str = zend_string_init("as DateTimeImmutable::add() does not modify the object itself", strlen("as DateTimeImmutable::add() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_add_0_arg0, attribute_NoDiscard_func_add_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_add_0->args[0].value, &attribute_NoDiscard_func_add_0_arg0); + attribute_NoDiscard_func_add_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_sub_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_sub_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "sub", sizeof("sub") - 1), attribute_name_NoDiscard_func_sub_0, 1); + zend_string_release(attribute_name_NoDiscard_func_sub_0); + zval attribute_NoDiscard_func_sub_0_arg0; + zend_string *attribute_NoDiscard_func_sub_0_arg0_str = zend_string_init("as DateTimeImmutable::sub() does not modify the object itself", strlen("as DateTimeImmutable::sub() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_sub_0_arg0, attribute_NoDiscard_func_sub_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_sub_0->args[0].value, &attribute_NoDiscard_func_sub_0_arg0); + attribute_NoDiscard_func_sub_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_settimezone_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_settimezone_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settimezone", sizeof("settimezone") - 1), attribute_name_NoDiscard_func_settimezone_0, 1); + zend_string_release(attribute_name_NoDiscard_func_settimezone_0); + zval attribute_NoDiscard_func_settimezone_0_arg0; + zend_string *attribute_NoDiscard_func_settimezone_0_arg0_str = zend_string_init("as DateTimeImmutable::setTimezone() does not modify the object itself", strlen("as DateTimeImmutable::setTimezone() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_settimezone_0_arg0, attribute_NoDiscard_func_settimezone_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settimezone_0->args[0].value, &attribute_NoDiscard_func_settimezone_0_arg0); + attribute_NoDiscard_func_settimezone_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_settime_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_settime_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settime", sizeof("settime") - 1), attribute_name_NoDiscard_func_settime_0, 1); + zend_string_release(attribute_name_NoDiscard_func_settime_0); + zval attribute_NoDiscard_func_settime_0_arg0; + zend_string *attribute_NoDiscard_func_settime_0_arg0_str = zend_string_init("as DateTimeImmutable::setTime() does not modify the object itself", strlen("as DateTimeImmutable::setTime() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_settime_0_arg0, attribute_NoDiscard_func_settime_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settime_0->args[0].value, &attribute_NoDiscard_func_settime_0_arg0); + attribute_NoDiscard_func_settime_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_setdate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_setdate_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setdate", sizeof("setdate") - 1), attribute_name_NoDiscard_func_setdate_0, 1); + zend_string_release(attribute_name_NoDiscard_func_setdate_0); + zval attribute_NoDiscard_func_setdate_0_arg0; + zend_string *attribute_NoDiscard_func_setdate_0_arg0_str = zend_string_init("as DateTimeImmutable::setDate() does not modify the object itself", strlen("as DateTimeImmutable::setDate() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_setdate_0_arg0, attribute_NoDiscard_func_setdate_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setdate_0->args[0].value, &attribute_NoDiscard_func_setdate_0_arg0); + attribute_NoDiscard_func_setdate_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_setisodate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_setisodate_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setisodate", sizeof("setisodate") - 1), attribute_name_NoDiscard_func_setisodate_0, 1); + zend_string_release(attribute_name_NoDiscard_func_setisodate_0); + zval attribute_NoDiscard_func_setisodate_0_arg0; + zend_string *attribute_NoDiscard_func_setisodate_0_arg0_str = zend_string_init("as DateTimeImmutable::setISODate() does not modify the object itself", strlen("as DateTimeImmutable::setISODate() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_setisodate_0_arg0, attribute_NoDiscard_func_setisodate_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setisodate_0->args[0].value, &attribute_NoDiscard_func_setisodate_0_arg0); + attribute_NoDiscard_func_setisodate_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_settimestamp_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_settimestamp_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settimestamp", sizeof("settimestamp") - 1), attribute_name_NoDiscard_func_settimestamp_0, 1); + zend_string_release(attribute_name_NoDiscard_func_settimestamp_0); + zval attribute_NoDiscard_func_settimestamp_0_arg0; + zend_string *attribute_NoDiscard_func_settimestamp_0_arg0_str = zend_string_init("as DateTimeImmutable::setTimestamp() does not modify the object itself", strlen("as DateTimeImmutable::setTimestamp() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_settimestamp_0_arg0, attribute_NoDiscard_func_settimestamp_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settimestamp_0->args[0].value, &attribute_NoDiscard_func_settimestamp_0_arg0); + attribute_NoDiscard_func_settimestamp_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_setmicrosecond_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_setmicrosecond_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setmicrosecond", sizeof("setmicrosecond") - 1), attribute_name_NoDiscard_func_setmicrosecond_0, 1); + zend_string_release(attribute_name_NoDiscard_func_setmicrosecond_0); + zval attribute_NoDiscard_func_setmicrosecond_0_arg0; + zend_string *attribute_NoDiscard_func_setmicrosecond_0_arg0_str = zend_string_init("as DateTimeImmutable::setMicrosecond() does not modify the object itself", strlen("as DateTimeImmutable::setMicrosecond() does not modify the object itself"), 1); + ZVAL_STR(&attribute_NoDiscard_func_setmicrosecond_0_arg0, attribute_NoDiscard_func_setmicrosecond_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setmicrosecond_0->args[0].value, &attribute_NoDiscard_func_setmicrosecond_0_arg0); + attribute_NoDiscard_func_setmicrosecond_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index e769c6caefb98..b1511c5c1c4df 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -233,6 +233,8 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D); void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D); bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D); +bool ZEND_FASTCALL zend_jit_nodiscard_helper(OPLINE_D); +bool ZEND_FASTCALL zend_jit_deprecated_nodiscard_helper(OPLINE_D); void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D); void ZEND_FASTCALL zend_jit_undefined_long_key_ex(zend_long key EXECUTE_DATA_DC); void ZEND_FASTCALL zend_jit_undefined_string_key(EXECUTE_DATA_D); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 69c80ff63304e..4d006c19d34e9 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -10153,7 +10153,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ir_GUARD_NOT( ir_AND_U32( ir_LOAD_U32(ir_ADD_OFFSET(func_ref, offsetof(zend_op_array, fn_flags))), - ir_CONST_U32(ZEND_ACC_DEPRECATED)), + ir_CONST_U32(ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD)), ir_CONST_ADDR(exit_addr)); } } @@ -10179,12 +10179,27 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (opline->opcode == ZEND_DO_FCALL || opline->opcode == ZEND_DO_FCALL_BY_NAME) { if (!func) { if (!trace) { - ir_ref if_deprecated, ret; + ir_ref if_deprecated_nodiscard, ret; - if_deprecated = ir_IF(ir_AND_U32( + uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if_deprecated_nodiscard = ir_IF(ir_AND_U32( ir_LOAD_U32(ir_ADD_OFFSET(func_ref, offsetof(zend_op_array, fn_flags))), - ir_CONST_U32(ZEND_ACC_DEPRECATED))); - ir_IF_TRUE_cold(if_deprecated); + ir_CONST_U32(ZEND_ACC_DEPRECATED|no_discard))); + ir_IF_TRUE_cold(if_deprecated_nodiscard); + + ir_ref helper = ir_CONST_FC_FUNC(no_discard ? zend_jit_deprecated_nodiscard_helper : zend_jit_deprecated_helper); + if (GCC_GLOBAL_REGS) { + ret = ir_CALL(IR_BOOL, helper); + } else { + ret = ir_CALL_1(IR_BOOL, helper, rx); + } + ir_GUARD(ret, jit_STUB_ADDR(jit, jit_stub_exception_handler)); + ir_MERGE_WITH_EMPTY_FALSE(if_deprecated_nodiscard); + } + } else { + if (func->common.fn_flags & ZEND_ACC_DEPRECATED) { + ir_ref ret; if (GCC_GLOBAL_REGS) { ret = ir_CALL(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_deprecated_helper)); @@ -10192,17 +10207,18 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ret = ir_CALL_1(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_deprecated_helper), rx); } ir_GUARD(ret, jit_STUB_ADDR(jit, jit_stub_exception_handler)); - ir_MERGE_WITH_EMPTY_FALSE(if_deprecated); } - } else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) { - ir_ref ret; - if (GCC_GLOBAL_REGS) { - ret = ir_CALL(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_deprecated_helper)); - } else { - ret = ir_CALL_1(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_deprecated_helper), rx); + if ((func->common.fn_flags & ZEND_ACC_NODISCARD) && !RETURN_VALUE_USED(opline)) { + ir_ref ret; + + if (GCC_GLOBAL_REGS) { + ret = ir_CALL(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_nodiscard_helper)); + } else { + ret = ir_CALL_1(IR_BOOL, ir_CONST_FC_FUNC(zend_jit_nodiscard_helper), rx); + } + ir_GUARD(ret, jit_STUB_ADDR(jit, jit_stub_exception_handler)); } - ir_GUARD(ret, jit_STUB_ADDR(jit, jit_stub_exception_handler)); } } diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index b7fb661615d1c..c98376d5a1f69 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -204,6 +204,54 @@ bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D) return 1; } +bool ZEND_FASTCALL zend_jit_nodiscard_helper(OPLINE_D) +{ + zend_execute_data *call = (zend_execute_data *) opline; + zend_function *fbc = call->func; + + zend_nodiscard_function(fbc); + + if (EG(exception)) { +#ifndef HAVE_GCC_GLOBAL_REGS + zend_execute_data *execute_data = EG(current_execute_data); +#endif + const zend_op *opline = EG(opline_before_exception); + if (opline && RETURN_VALUE_USED(opline)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + + zend_vm_stack_free_args(call); + + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + zend_vm_stack_free_call_frame(call); + return 0; + } + return 1; +} + +bool ZEND_FASTCALL zend_jit_deprecated_nodiscard_helper(OPLINE_D) +{ + zend_execute_data *call = (zend_execute_data *) opline; + zend_function *fbc = call->func; + + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + if (zend_jit_deprecated_helper(OPLINE_C) == 0) { + return 0; + } + } + + if (fbc->common.fn_flags & ZEND_ACC_NODISCARD) { + if (zend_jit_nodiscard_helper(OPLINE_C) == 0) { + return 0; + } + } + + return 1; +} + void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D) { const zend_op *opline = EX(opline); diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index e7f4ff8844714..b6533d8dc20e8 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2732,6 +2732,7 @@ function proc_nice(int $priority): bool {} * @param resource $stream * @param int $would_block */ +#[\NoDiscard(message: "as locking the stream might have failed")] function flock($stream, int $operation, &$would_block = null): bool {} /** diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 3d92288643159..d35377c900735 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 85677dc3476d25b7820fd3a26fe39f2e9378b6e7 */ + * Stub hash: 824ccb41163307bd0fad452b705a8222b6f42d09 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -3205,7 +3205,7 @@ static const zend_function_entry ext_functions[] = { #if defined(HAVE_NICE) ZEND_FE(proc_nice, arginfo_proc_nice) #endif - ZEND_FE(flock, arginfo_flock) + ZEND_RAW_FENTRY("flock", zif_flock, arginfo_flock, ZEND_ACC_NODISCARD, NULL, NULL) ZEND_FE(get_meta_tags, arginfo_get_meta_tags) ZEND_FE(pclose, arginfo_pclose) ZEND_FE(popen, arginfo_popen) @@ -4039,6 +4039,15 @@ static void register_basic_functions_symbols(int module_number) ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_decode_0->args[1].value, &attribute_Deprecated_func_utf8_decode_0_arg1); attribute_Deprecated_func_utf8_decode_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_string *attribute_name_NoDiscard_func_flock_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_flock_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "flock", sizeof("flock") - 1), attribute_name_NoDiscard_func_flock_0, 1); + zend_string_release(attribute_name_NoDiscard_func_flock_0); + zval attribute_NoDiscard_func_flock_0_arg0; + zend_string *attribute_NoDiscard_func_flock_0_arg0_str = zend_string_init("as locking the stream might have failed", strlen("as locking the stream might have failed"), 1); + ZVAL_STR(&attribute_NoDiscard_func_flock_0_arg0, attribute_NoDiscard_func_flock_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_flock_0->args[0].value, &attribute_NoDiscard_func_flock_0_arg0); + attribute_NoDiscard_func_flock_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_hash", sizeof("password_hash") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_verify", sizeof("password_verify") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); diff --git a/ext/standard/tests/file/userstreams_004.phpt b/ext/standard/tests/file/userstreams_004.phpt index 959f02f5b1cd7..fa68e5aa9307a 100644 --- a/ext/standard/tests/file/userstreams_004.phpt +++ b/ext/standard/tests/file/userstreams_004.phpt @@ -19,7 +19,7 @@ class test_wrapper extends test_wrapper_base { } function test($name, $fd, $mode) { echo "------ $name: -------\n"; - flock($fd, $mode); + (void)flock($fd, $mode); $data = stream_get_meta_data($fd); var_dump($data['wrapper_data']->mode === $mode); } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 565895dac72e1..b9190f6753052 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -124,6 +124,13 @@ static ZEND_FUNCTION(zend_test_deprecated_attr) ZEND_PARSE_PARAMETERS_NONE(); } +static ZEND_FUNCTION(zend_test_deprecated_nodiscard) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_LONG(1); +} + /* Create a string without terminating null byte. Must be terminated with * zend_terminate_string() before destruction, otherwise a warning is issued * in debug builds. */ diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index e0e1f32833ef5..921dadd00ce15 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -218,6 +218,11 @@ function zend_test_deprecated(mixed $arg = null): void {} #[\Deprecated(message: "custom message")] function zend_test_deprecated_attr(): void {} + + #[\Deprecated(message: "custom message")] + #[\NoDiscard(message: "custom message 2")] + function zend_test_deprecated_nodiscard(): int {} + /** @alias zend_test_void_return */ function zend_test_aliased(): void {} diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index f13df2ae4bea2..391f2fc500b02 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 80b2dbc373baccd5ee4df047070d95e4c44effcd */ + * Stub hash: eebe535d0295f707201ff751e38a5ad3837dbbd2 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -22,6 +22,9 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_deprecated_attr arginfo_zend_test_void_return +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_deprecated_nodiscard, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + #define arginfo_zend_test_aliased arginfo_zend_test_void_return #define arginfo_zend_test_deprecated_aliased arginfo_zend_test_void_return @@ -128,8 +131,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_is_string_marked_as_va ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_get_map_ptr_last, 0, 0, IS_LONG, 0) -ZEND_END_ARG_INFO() +#define arginfo_zend_get_map_ptr_last arginfo_zend_test_deprecated_nodiscard ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_crash, 0, 0, IS_VOID, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, message, IS_STRING, 1, "null") @@ -187,7 +189,7 @@ ZEND_END_ARG_INFO() #define arginfo_ZendTestNS2_ZendSubNS_namespaced_deprecated_aliased_func arginfo_zend_test_void_return -#define arginfo_class__ZendTestClass_is_object arginfo_zend_get_map_ptr_last +#define arginfo_class__ZendTestClass_is_object arginfo_zend_test_deprecated_nodiscard #define arginfo_class__ZendTestClass___toString arginfo_zend_get_current_func_name @@ -262,6 +264,7 @@ static ZEND_FUNCTION(zend_test_void_return); static ZEND_FUNCTION(zend_test_compile_string); static ZEND_FUNCTION(zend_test_deprecated); static ZEND_FUNCTION(zend_test_deprecated_attr); +static ZEND_FUNCTION(zend_test_deprecated_nodiscard); static ZEND_FUNCTION(zend_create_unterminated_string); static ZEND_FUNCTION(zend_terminate_string); static ZEND_FUNCTION(zend_leak_variable); @@ -358,6 +361,11 @@ static const zend_function_entry ext_functions[] = { #else ZEND_RAW_FENTRY("zend_test_deprecated_attr", zif_zend_test_deprecated_attr, arginfo_zend_test_deprecated_attr, ZEND_ACC_DEPRECATED) #endif +#if (PHP_VERSION_ID >= 80400) + ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD, NULL, NULL) +#else + ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD) +#endif #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY("zend_test_aliased", zif_zend_test_void_return, arginfo_zend_test_aliased, 0, NULL, NULL) #else @@ -564,6 +572,24 @@ static void register_test_symbols(int module_number) ZVAL_COPY_VALUE(&attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].value, &attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0); attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_string *attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); + zend_attribute *attribute_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_nodiscard", sizeof("zend_test_deprecated_nodiscard") - 1), attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0, 1); + zend_string_release(attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0); + zval attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0; + zend_string *attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); + ZVAL_STR(&attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0, attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_Deprecated_func_zend_test_deprecated_nodiscard_0->args[0].value, &attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0); + attribute_Deprecated_func_zend_test_deprecated_nodiscard_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_nodiscard", sizeof("zend_test_deprecated_nodiscard") - 1), attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1, 1); + zend_string_release(attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1); + zval attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0; + zend_string *attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0_str = zend_string_init("custom message 2", strlen("custom message 2"), 1); + ZVAL_STR(&attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0, attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1->args[0].value, &attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0); + attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_string *attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); zend_attribute *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1), 0, attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0, 1); zend_string_release(attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0); From 169a6c63f0925ea3e90142675d519672d6309aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 2 Apr 2025 09:37:00 +0200 Subject: [PATCH 251/503] zend_execute: Remove useless refcounting in `get_deprecation_suffix_from_attribute()` (#18229) --- Zend/zend_execute.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index e7f7d19118d3b..4fed2af3a92fd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1850,14 +1850,14 @@ ZEND_COLD static zend_result ZEND_FASTCALL get_deprecation_suffix_from_attribute z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL); ZEND_ASSERT(z != &EG(uninitialized_zval)); if (Z_TYPE_P(z) == IS_STRING) { - message = zend_string_copy(Z_STR_P(z)); + message = Z_STR_P(z); } /* Extract the $since property. */ z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_SINCE), false, NULL); ZEND_ASSERT(z != &EG(uninitialized_zval)); if (Z_TYPE_P(z) == IS_STRING) { - since = zend_string_copy(Z_STR_P(z)); + since = Z_STR_P(z); } /* Construct the suffix. */ @@ -1874,8 +1874,6 @@ ZEND_COLD static zend_result ZEND_FASTCALL get_deprecation_suffix_from_attribute out: - zend_string_release(since); - zend_string_release(message); zval_ptr_dtor(&obj); return result; From a9d4b49252223ae1e29f01ac0cc4036e04a0acc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 2 Apr 2025 10:38:28 +0200 Subject: [PATCH 252/503] Fix path for main/debug_gdb_scripts.c in .gitattributes The previous path `main/gdb_inlined_script.c` never existed in any commit merged to master. see 46b6ad6daeb84ef47d17ca190dc960f604a493ca --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 86797917210fa..c4e1bd57b2a4b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -21,7 +21,7 @@ # Collapse generated files within git and pull request diff. **/*_arginfo.h linguist-generated -diff -/main/gdb_inlined_script.c linguist-generated -diff +/main/debug_gdb_scripts.c linguist-generated -diff /Zend/zend_vm_execute.h linguist-generated -diff /Zend/zend_vm_handlers.h linguist-generated -diff /Zend/zend_vm_opcodes.[ch] linguist-generated -diff From 02d58faad4f0ea5df7be241c9238131bb9717c0c Mon Sep 17 00:00:00 2001 From: Luis Carilla Ternero <101694456+lcarilla@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:56:16 +0200 Subject: [PATCH 253/503] GDB: replace match statements with if statements in gdb debug script so it works with lower versions (#18226) --- main/debug_gdb_scripts.c | 125 +++++++++++++++++++-------------------- scripts/gdb/php_gdb.py | 125 +++++++++++++++++++-------------------- 2 files changed, 120 insertions(+), 130 deletions(-) diff --git a/main/debug_gdb_scripts.c b/main/debug_gdb_scripts.c index f369e0945cda9..3806f6aab60dd 100644 --- a/main/debug_gdb_scripts.c +++ b/main/debug_gdb_scripts.c @@ -782,28 +782,27 @@ asm( ".ascii \" for bit in range(0, type_mask_size):\\n\"\n" ".ascii \" if type_mask & (1 << bit):\\n\"\n" ".ascii \" type_name = ZendTypeBits.zendTypeName(bit)\\n\"\n" - ".ascii \" match type_name:\\n\"\n" - ".ascii \" case None:\\n\"\n" - ".ascii \" parts.append('(1<<%d)' % bit)\\n\"\n" - ".ascii \" case 'list':\\n\"\n" - ".ascii \" list = t['ptr'].cast(gdb.lookup_type('zend_type_list').pointer())\\n\"\n" - ".ascii \" num_types = int(list['num_types'])\\n\"\n" - ".ascii \" types = list['types'].dereference().cast(gdb.lookup_type('zend_type').array(num_types))\\n\"\n" - ".ascii \" for i in range(0, num_types):\\n\"\n" - ".ascii \" str = self.format_type(types[i])\\n\"\n" - ".ascii \" if any((c in set('|&()')) for c in str):\\n\"\n" - ".ascii \" str = '(%s)' % str\\n\"\n" - ".ascii \" parts.append(str)\\n\"\n" - ".ascii \" case 'union' | 'arena':\\n\"\n" - ".ascii \" meta.append(type_name)\\n\"\n" - ".ascii \" case 'intersection':\\n\"\n" - ".ascii \" meta.append(type_name)\\n\"\n" - ".ascii \" separator = '&'\\n\"\n" - ".ascii \" case 'name':\\n\"\n" - ".ascii \" str = t['ptr'].cast(gdb.lookup_type('zend_string').pointer())\\n\"\n" - ".ascii \" parts.append(format_zstr(str))\\n\"\n" - ".ascii \" case _:\\n\"\n" - ".ascii \" parts.append(type_name)\\n\"\n" + ".ascii \" if type_name is None:\\n\"\n" + ".ascii \" parts.append('(1<<%d)' % bit)\\n\"\n" + ".ascii \" elif type_name == 'list':\\n\"\n" + ".ascii \" list_ptr = t['ptr'].cast(gdb.lookup_type('zend_type_list').pointer())\\n\"\n" + ".ascii \" num_types = int(list_ptr['num_types'])\\n\"\n" + ".ascii \" types = list_ptr['types'].dereference().cast(gdb.lookup_type('zend_type').array(num_types))\\n\"\n" + ".ascii \" for i in range(0, num_types):\\n\"\n" + ".ascii \" type_str = self.format_type(types[i])\\n\"\n" + ".ascii \" if any((c in set('|&()')) for c in type_str):\\n\"\n" + ".ascii \" type_str = '(%s)' % type_str\\n\"\n" + ".ascii \" parts.append(type_str)\\n\"\n" + ".ascii \" elif type_name == 'union' or type_name == 'arena':\\n\"\n" + ".ascii \" meta.append(type_name)\\n\"\n" + ".ascii \" elif type_name == 'intersection':\\n\"\n" + ".ascii \" meta.append(type_name)\\n\"\n" + ".ascii \" separator = '&'\\n\"\n" + ".ascii \" elif type_name == 'name':\\n\"\n" + ".ascii \" name_str = t['ptr'].cast(gdb.lookup_type('zend_string').pointer())\\n\"\n" + ".ascii \" parts.append(format_zstr(name_str))\\n\"\n" + ".ascii \" else:\\n\"\n" + ".ascii \" parts.append(type_name)\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" str = separator.join(parts)\\n\"\n" ".ascii \"\\n\"\n" @@ -1073,15 +1072,15 @@ asm( ".ascii \" self.val = val\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" def to_string(self):\\n\"\n" - ".ascii \" match int(self.val['type']):\\n\"\n" - ".ascii \" case ZendFnTypes.ZEND_INTERNAL_FUNCTION:\\n\"\n" - ".ascii \" typestr = 'internal'\\n\"\n" - ".ascii \" case ZendFnTypes.ZEND_USER_FUNCTION:\\n\"\n" - ".ascii \" typestr = 'user'\\n\"\n" - ".ascii \" case ZendFnTypes.ZEND_EVAL_CODE:\\n\"\n" - ".ascii \" typestr = 'eval'\\n\"\n" - ".ascii \" case _:\\n\"\n" - ".ascii \" typestr = '\?\?\?'\\n\"\n" + ".ascii \" val_type = int(self.val['type'])\\n\"\n" + ".ascii \" if val_type == ZendFnTypes.ZEND_INTERNAL_FUNCTION:\\n\"\n" + ".ascii \" typestr = 'internal'\\n\"\n" + ".ascii \" elif val_type == ZendFnTypes.ZEND_USER_FUNCTION:\\n\"\n" + ".ascii \" typestr = 'user'\\n\"\n" + ".ascii \" elif val_type == ZendFnTypes.ZEND_EVAL_CODE:\\n\"\n" + ".ascii \" typestr = 'eval'\\n\"\n" + ".ascii \" else:\\n\"\n" + ".ascii \" typestr = '\?\?\?'\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" if self.val['common']['function_name']:\\n\"\n" ".ascii \" namestr = format_zstr(self.val['common']['function_name'])\\n\"\n" @@ -1501,13 +1500,12 @@ asm( ".ascii \"\\n\"\n" ".ascii \" bits = self._bits\\n\"\n" ".ascii \" type_bits = None\\n\"\n" - ".ascii \" match type_name:\\n\"\n" - ".ascii \" case 'string':\\n\"\n" - ".ascii \" type_bits = self._str_bits\\n\"\n" - ".ascii \" case 'array':\\n\"\n" - ".ascii \" type_bits = self._array_bits\\n\"\n" - ".ascii \" case 'object':\\n\"\n" - ".ascii \" type_bits = self._obj_bits\\n\"\n" + ".ascii \" if type_name == 'string':\\n\"\n" + ".ascii \" type_bits = self._str_bits\\n\"\n" + ".ascii \" elif type_name == 'array':\\n\"\n" + ".ascii \" type_bits = self._array_bits\\n\"\n" + ".ascii \" elif type_name == 'object':\\n\"\n" + ".ascii \" type_bits = self._obj_bits\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" type_flags = flags & self._flags_mask\\n\"\n" ".ascii \" for i in range(0, 31):\\n\"\n" @@ -1530,15 +1528,14 @@ asm( ".ascii \"\\n\"\n" ".ascii \" if (flags & (1<> self._info_shift) & self._gc_color\\n\"\n" - ".ascii \" match gc_color:\\n\"\n" - ".ascii \" case self._gc_black:\\n\"\n" - ".ascii \" names.append('GC_BLACK')\\n\"\n" - ".ascii \" case self._gc_white:\\n\"\n" - ".ascii \" names.append('GC_WHITE')\\n\"\n" - ".ascii \" case self._gc_grey:\\n\"\n" - ".ascii \" names.append('GC_GREY')\\n\"\n" - ".ascii \" case self._gc_purple:\\n\"\n" - ".ascii \" names.append('GC_PURPLE')\\n\"\n" + ".ascii \" if gc_color == self._gc_black:\\n\"\n" + ".ascii \" names.append('GC_BLACK')\\n\"\n" + ".ascii \" elif gc_color == self._gc_white:\\n\"\n" + ".ascii \" names.append('GC_WHITE')\\n\"\n" + ".ascii \" elif gc_color == self._gc_grey:\\n\"\n" + ".ascii \" names.append('GC_GREY')\\n\"\n" + ".ascii \" elif gc_color == self._gc_purple:\\n\"\n" + ".ascii \" names.append('GC_PURPLE')\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" gc_address = (flags >> self._info_shift) & self._gc_address\\n\"\n" ".ascii \" if gc_address != 0:\\n\"\n" @@ -1577,17 +1574,16 @@ asm( ".ascii \" pattern = re.compile(r'#define (GC_[^\\\\s]+)\\\\s+((0x)\?[0-9a-f]+)')\\n\"\n" ".ascii \" matches = pattern.findall(content)\\n\"\n" ".ascii \" for name, bit, _ in matches:\\n\"\n" - ".ascii \" match name:\\n\"\n" - ".ascii \" case 'GC_TYPE_MASK':\\n\"\n" - ".ascii \" self._type_mask = int(bit, 0)\\n\"\n" - ".ascii \" case 'GC_FLAGS_MASK':\\n\"\n" - ".ascii \" self._flags_mask = int(bit, 0)\\n\"\n" - ".ascii \" case 'GC_INFO_MASK':\\n\"\n" - ".ascii \" self._info_mask = int(bit, 0)\\n\"\n" - ".ascii \" case 'GC_INFO_SHIFT':\\n\"\n" - ".ascii \" self._info_shift = int(bit, 0)\\n\"\n" - ".ascii \" case 'GC_FLAGS_SHIFT':\\n\"\n" - ".ascii \" self._flags_shift = int(bit, 0)\\n\"\n" + ".ascii \" if name == 'GC_TYPE_MASK':\\n\"\n" + ".ascii \" self._type_mask = int(bit, 0)\\n\"\n" + ".ascii \" elif name == 'GC_FLAGS_MASK':\\n\"\n" + ".ascii \" self._flags_mask = int(bit, 0)\\n\"\n" + ".ascii \" elif name == 'GC_INFO_MASK':\\n\"\n" + ".ascii \" self._info_mask = int(bit, 0)\\n\"\n" + ".ascii \" elif name == 'GC_INFO_SHIFT':\\n\"\n" + ".ascii \" self._info_shift = int(bit, 0)\\n\"\n" + ".ascii \" elif name == 'GC_FLAGS_SHIFT':\\n\"\n" + ".ascii \" self._flags_shift = int(bit, 0)\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" # IS_STR_INTERNED GC_IMMUTABLE\\n\"\n" ".ascii \" # IS_STR_PERMANENT (1<<8)\\n\"\n" @@ -1598,13 +1594,12 @@ asm( ".ascii \" bit = bits.get(val)\\n\"\n" ".ascii \" if bit == None:\\n\"\n" ".ascii \" continue\\n\"\n" - ".ascii \" match type:\\n\"\n" - ".ascii \" case 'STR':\\n\"\n" - ".ascii \" target = str_bits\\n\"\n" - ".ascii \" case 'ARRAY':\\n\"\n" - ".ascii \" target = array_bits\\n\"\n" - ".ascii \" case 'OBJ':\\n\"\n" - ".ascii \" target = obj_bits\\n\"\n" + ".ascii \" if type == 'STR':\\n\"\n" + ".ascii \" target = str_bits\\n\"\n" + ".ascii \" elif type == 'ARRAY':\\n\"\n" + ".ascii \" target = array_bits\\n\"\n" + ".ascii \" elif type == 'OBJ':\\n\"\n" + ".ascii \" target = obj_bits\\n\"\n" ".ascii \" target[name] = int(bit)\\n\"\n" ".ascii \"\\n\"\n" ".ascii \" # Hard coded because these are not exposed in header files\\n\"\n" diff --git a/scripts/gdb/php_gdb.py b/scripts/gdb/php_gdb.py index 724cef6cf19e9..ae8396a2ac0c2 100644 --- a/scripts/gdb/php_gdb.py +++ b/scripts/gdb/php_gdb.py @@ -112,28 +112,27 @@ def format_type(self, t): for bit in range(0, type_mask_size): if type_mask & (1 << bit): type_name = ZendTypeBits.zendTypeName(bit) - match type_name: - case None: - parts.append('(1<<%d)' % bit) - case 'list': - list = t['ptr'].cast(gdb.lookup_type('zend_type_list').pointer()) - num_types = int(list['num_types']) - types = list['types'].dereference().cast(gdb.lookup_type('zend_type').array(num_types)) - for i in range(0, num_types): - str = self.format_type(types[i]) - if any((c in set('|&()')) for c in str): - str = '(%s)' % str - parts.append(str) - case 'union' | 'arena': - meta.append(type_name) - case 'intersection': - meta.append(type_name) - separator = '&' - case 'name': - str = t['ptr'].cast(gdb.lookup_type('zend_string').pointer()) - parts.append(format_zstr(str)) - case _: - parts.append(type_name) + if type_name is None: + parts.append('(1<<%d)' % bit) + elif type_name == 'list': + list_ptr = t['ptr'].cast(gdb.lookup_type('zend_type_list').pointer()) + num_types = int(list_ptr['num_types']) + types = list_ptr['types'].dereference().cast(gdb.lookup_type('zend_type').array(num_types)) + for i in range(0, num_types): + type_str = self.format_type(types[i]) + if any((c in set('|&()')) for c in type_str): + type_str = '(%s)' % type_str + parts.append(type_str) + elif type_name == 'union' or type_name == 'arena': + meta.append(type_name) + elif type_name == 'intersection': + meta.append(type_name) + separator = '&' + elif type_name == 'name': + name_str = t['ptr'].cast(gdb.lookup_type('zend_string').pointer()) + parts.append(format_zstr(name_str)) + else: + parts.append(type_name) str = separator.join(parts) @@ -403,15 +402,15 @@ def __init__(self, val): self.val = val def to_string(self): - match int(self.val['type']): - case ZendFnTypes.ZEND_INTERNAL_FUNCTION: - typestr = 'internal' - case ZendFnTypes.ZEND_USER_FUNCTION: - typestr = 'user' - case ZendFnTypes.ZEND_EVAL_CODE: - typestr = 'eval' - case _: - typestr = '???' + val_type = int(self.val['type']) + if val_type == ZendFnTypes.ZEND_INTERNAL_FUNCTION: + typestr = 'internal' + elif val_type == ZendFnTypes.ZEND_USER_FUNCTION: + typestr = 'user' + elif val_type == ZendFnTypes.ZEND_EVAL_CODE: + typestr = 'eval' + else: + typestr = '???' if self.val['common']['function_name']: namestr = format_zstr(self.val['common']['function_name']) @@ -831,13 +830,12 @@ def format(self, flags): bits = self._bits type_bits = None - match type_name: - case 'string': - type_bits = self._str_bits - case 'array': - type_bits = self._array_bits - case 'object': - type_bits = self._obj_bits + if type_name == 'string': + type_bits = self._str_bits + elif type_name == 'array': + type_bits = self._array_bits + elif type_name == 'object': + type_bits = self._obj_bits type_flags = flags & self._flags_mask for i in range(0, 31): @@ -860,15 +858,14 @@ def format(self, flags): if (flags & (1<> self._info_shift) & self._gc_color - match gc_color: - case self._gc_black: - names.append('GC_BLACK') - case self._gc_white: - names.append('GC_WHITE') - case self._gc_grey: - names.append('GC_GREY') - case self._gc_purple: - names.append('GC_PURPLE') + if gc_color == self._gc_black: + names.append('GC_BLACK') + elif gc_color == self._gc_white: + names.append('GC_WHITE') + elif gc_color == self._gc_grey: + names.append('GC_GREY') + elif gc_color == self._gc_purple: + names.append('GC_PURPLE') gc_address = (flags >> self._info_shift) & self._gc_address if gc_address != 0: @@ -907,17 +904,16 @@ def _load(self): pattern = re.compile(r'#define (GC_[^\s]+)\s+((0x)?[0-9a-f]+)') matches = pattern.findall(content) for name, bit, _ in matches: - match name: - case 'GC_TYPE_MASK': - self._type_mask = int(bit, 0) - case 'GC_FLAGS_MASK': - self._flags_mask = int(bit, 0) - case 'GC_INFO_MASK': - self._info_mask = int(bit, 0) - case 'GC_INFO_SHIFT': - self._info_shift = int(bit, 0) - case 'GC_FLAGS_SHIFT': - self._flags_shift = int(bit, 0) + if name == 'GC_TYPE_MASK': + self._type_mask = int(bit, 0) + elif name == 'GC_FLAGS_MASK': + self._flags_mask = int(bit, 0) + elif name == 'GC_INFO_MASK': + self._info_mask = int(bit, 0) + elif name == 'GC_INFO_SHIFT': + self._info_shift = int(bit, 0) + elif name == 'GC_FLAGS_SHIFT': + self._flags_shift = int(bit, 0) # IS_STR_INTERNED GC_IMMUTABLE # IS_STR_PERMANENT (1<<8) @@ -928,13 +924,12 @@ def _load(self): bit = bits.get(val) if bit == None: continue - match type: - case 'STR': - target = str_bits - case 'ARRAY': - target = array_bits - case 'OBJ': - target = obj_bits + if type == 'STR': + target = str_bits + elif type == 'ARRAY': + target = array_bits + elif type == 'OBJ': + target = obj_bits target[name] = int(bit) # Hard coded because these are not exposed in header files From 2e47442a6b1e9a47d449008df2a853e6e99fada3 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 1 Apr 2025 18:58:31 +0100 Subject: [PATCH 254/503] Fix GH-18212: fseek with SEEK_CUR and negative offset crash on debug Triggers the assertion as with SEEK_CUR the stream position is set to a negative value so we force the failure without affecting its position instead. close GH-18224 --- NEWS | 2 ++ ext/standard/tests/file/gh18212.phpt | 13 +++++++++++++ ext/standard/tests/file/stream_rfc2397_007.phpt | 2 +- main/streams/streams.c | 4 ++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/file/gh18212.phpt diff --git a/NEWS b/NEWS index 37a320d27be07..335903eee23c0 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) + . Fixed bug GH-18212 (fseek with SEEK_CUR whence value and negative offset + leads to negative stream position). (David Carlier) 10 Apr 2025, PHP 8.3.20 diff --git a/ext/standard/tests/file/gh18212.phpt b/ext/standard/tests/file/gh18212.phpt new file mode 100644 index 0000000000000..6e4d8ad9bd328 --- /dev/null +++ b/ext/standard/tests/file/gh18212.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-18212: fseek with SEEK_CUR and negative offset leads to negative file stream position. +--FILE-- + +--EXPECT-- +int(-1) +int(-1) + diff --git a/ext/standard/tests/file/stream_rfc2397_007.phpt b/ext/standard/tests/file/stream_rfc2397_007.phpt index dcbe5beeb3dc9..49a037e855fbd 100644 --- a/ext/standard/tests/file/stream_rfc2397_007.phpt +++ b/ext/standard/tests/file/stream_rfc2397_007.phpt @@ -118,7 +118,7 @@ int(2) bool(false) ===S:-10,C=== int(-1) -bool(false) +int(2) bool(false) ===S:3,S=== int(0) diff --git a/main/streams/streams.c b/main/streams/streams.c index 7a5dc2a58aaf1..4e0aaa53b443e 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1390,6 +1390,10 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) } whence = SEEK_SET; break; + case SEEK_SET: + if (offset < 0) { + return -1; + } } ret = stream->ops->seek(stream, offset, whence, &stream->position); From 79dc7a2d269c2c3ff38e51c1aad12f6fc6d96a1b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 2 Apr 2025 16:20:09 +0300 Subject: [PATCH 255/503] Update IR IR commit: 8d17022fb61ebfed9f6be81a8182ea31202697ed --- ext/opcache/jit/ir/ir_x86.dasc | 70 ++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index ad785d3b891eb..d01a8c41359aa 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -650,6 +650,26 @@ IR_ALWAYS_INLINE ir_mem IR_MEM(ir_reg base, int32_t offset, ir_reg index, int32_ || } |.endmacro +/* Like ASM_REG_IMM_OP, but op1 accepts r16,r32,r64 (not r8) */ +|.macro ASM_REG16_IMM_OP, op, type, op1, op2 +|| switch (ir_type_size[type]) { +|| default: +|| IR_ASSERT(0); +|| case 1: +|| case 2: +| op Rw(op1), (op2 & 0xffff) +|| break; +|| case 4: +| op Rd(op1), op2 +|| break; +|.if X64 +|| case 8: +| op Rq(op1), op2 +|| break; +|.endif +|| } +|.endmacro + |.macro ASM_MEM_REG_OP, op, type, op1, op2 | ASM_EXPAND_OP1_MEM ASM_EXPAND_TYPE_MEM_REG, op, type, op1, op2 |.endmacro @@ -1066,6 +1086,7 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(SSE_CEIL) \ _(SSE_TRUNC) \ _(SSE_NEARBYINT) \ + _(BIT_OP) \ #define IR_LEA_FIRST IR_LEA_OB #define IR_LEA_LAST IR_LEA_O_SYM @@ -1400,6 +1421,7 @@ op2_const: case IR_DIV_PWR2: case IR_OP_INT: case IR_OP_FP: + case IR_BIT_OP: flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG; break; case IR_MOD_PWR2: @@ -2280,6 +2302,9 @@ binop_fp: // return IR_COPY_INT; } else if (op2_insn->val.i64 == -1) { // -1 + } else if (IR_IS_POWER_OF_TWO(op2_insn->val.u64) && !IR_IS_SIGNED_32BIT(op2_insn->val.i64)) { + /* OR(X, PWR2) => BTS */ + return IR_BIT_OP; } } goto binop_int; @@ -2294,6 +2319,9 @@ binop_fp: // 0 } else if (op2_insn->val.i64 == -1) { // return IR_COPY_INT; + } else if (IR_IS_POWER_OF_TWO(~op2_insn->val.u64) && !IR_IS_SIGNED_32BIT(op2_insn->val.i64)) { + /* AND(X, ~PWR2) => BTR */ + return IR_BIT_OP; } } goto binop_int; @@ -4341,6 +4369,45 @@ static void ir_emit_mul_div_mod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn) } } +static void ir_emit_bit_op(ir_ctx *ctx, ir_ref def, ir_insn *insn) +{ + ir_backend_data *data = ctx->data; + dasm_State **Dst = &data->dasm_state; + ir_type type = insn->type; + ir_ref op1 = insn->op1; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); + ir_reg op1_reg = ctx->regs[def][1]; + + IR_ASSERT(IR_IS_CONST_REF(insn->op2)); + IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op)); + IR_ASSERT(def_reg != IR_REG_NONE); + + if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) { + op1_reg = IR_REG_NUM(op1_reg); + ir_emit_load(ctx, type, op1_reg, op1); + } + if (def_reg != op1_reg) { + if (op1_reg != IR_REG_NONE) { + ir_emit_mov(ctx, type, def_reg, op1_reg); + } else { + ir_emit_load(ctx, type, def_reg, op1); + } + } + if (insn->op == IR_OR) { + uint32_t bit = IR_LOG2(ctx->ir_base[insn->op2].val.u64); + + | ASM_REG16_IMM_OP, bts, type, def_reg, bit + } else { + IR_ASSERT(insn->op == IR_AND); + uint32_t bit = IR_LOG2(~ctx->ir_base[insn->op2].val.u64); + + | ASM_REG16_IMM_OP, btr, type, def_reg, bit + } + if (IR_REG_SPILLED(ctx->regs[def][0])) { + ir_emit_store(ctx, type, def, def_reg); + } +} + static void ir_emit_sdiv_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn) { ir_backend_data *data = ctx->data; @@ -10668,6 +10735,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) case IR_MOD_PWR2: ir_emit_mul_div_mod_pwr2(ctx, i, insn); break; + case IR_BIT_OP: + ir_emit_bit_op(ctx, i, insn); + break; case IR_SDIV_PWR2: ir_emit_sdiv_pwr2(ctx, i, insn); break; From 1f6fdde6469675058509a27f2bd3325b2b01910b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 16 Oct 2024 18:58:42 +0200 Subject: [PATCH 256/503] Implement asymmetric visibility for static properties https://wiki.php.net/rfc/static-aviz Optimally, this would be moved to zend_fetch_static_property_address(). However, this isn't currently effective for opcache, because R and RW/W/UNSET cache slots are merged. This will circumvent the visibility check if the cache is primed by a R instruction. Closes GH-16486 --- UPGRADING | 2 + .../asymmetric_visibility/static_props.phpt | 139 +++++++++++++++++- Zend/zend_compile.c | 4 - Zend/zend_vm_def.h | 43 +++++- Zend/zend_vm_execute.h | 43 +++++- 5 files changed, 224 insertions(+), 7 deletions(-) diff --git a/UPGRADING b/UPGRADING index c8d45b54544d6..9dfc984f8917d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -122,6 +122,8 @@ PHP 8.5 UPGRADE NOTES it can be used to suppress warnings emitted by #[\NoDiscard] and possibly also diagnostics emitted by external IDEs or static analysis tools. RFC: https://wiki.php.net/rfc/marking_return_value_as_important + . Added asymmetric visibility support for static properties. + RFC: https://wiki.php.net/rfc/static-aviz - Curl: . Added support for share handles that are persisted across multiple PHP diff --git a/Zend/tests/asymmetric_visibility/static_props.phpt b/Zend/tests/asymmetric_visibility/static_props.phpt index 65fd3aa1923d2..f47dcf70b6f74 100644 --- a/Zend/tests/asymmetric_visibility/static_props.phpt +++ b/Zend/tests/asymmetric_visibility/static_props.phpt @@ -5,8 +5,145 @@ Asymmetric visibility on static props class C { public private(set) static int $prop; + public private(set) static array $prop2; + public private(set) static stdClass $prop3; + public private(set) static object $unset; + + public static function reset() { + self::$prop = 1; + self::$prop2 = []; + self::$prop3 = new stdClass(); + } + + public static function setProp($prop) { + self::$prop = $prop; + } + + public static function addProp2($prop2) { + self::$prop2[] = $prop2; + } +} + +function test() { + C::reset(); + + try { + C::$prop = 2; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + C::setProp(3); + var_dump(C::$prop); + + try { + ++C::$prop; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + try { + C::$prop++; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + try { + C::$prop += str_repeat('a', 10); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + try { + $ref = &C::$prop; + $ref++; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + try { + $ref = 4; + C::$prop = &$ref; + $ref++; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop); + + try { + C::$prop2[] = 'foo'; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump(C::$prop2); + + C::addProp2('bar'); + var_dump(C::$prop2); + + C::$prop3->foo = 'foo'; + var_dump(C::$prop3); + + unset(C::$unset->foo); } +test(); +echo "\nRepeat:\n"; +test(); + ?> --EXPECTF-- -Fatal error: Static property may not have asymmetric visibility in %s on line %d +Cannot modify private(set) property C::$prop from global scope +int(1) +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop2 from global scope +array(0) { +} +array(1) { + [0]=> + string(3) "bar" +} +object(stdClass)#%d (1) { + ["foo"]=> + string(3) "foo" +} + +Repeat: +Cannot modify private(set) property C::$prop from global scope +int(1) +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop from global scope +int(3) +Cannot indirectly modify private(set) property C::$prop2 from global scope +array(0) { +} +array(1) { + [0]=> + string(3) "bar" +} +object(stdClass)#%d (1) { + ["foo"]=> + string(3) "foo" +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c1988fdaa1535..2e405de30ea62 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8694,10 +8694,6 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f zend_error_noreturn(E_COMPILE_ERROR, "Property cannot be both final and private"); } - if ((flags & ZEND_ACC_STATIC) && (flags & ZEND_ACC_PPP_SET_MASK)) { - zend_error_noreturn(E_COMPILE_ERROR, "Static property may not have asymmetric visibility"); - } - if (ce->ce_flags & ZEND_ACC_INTERFACE) { if (flags & ZEND_ACC_FINAL) { zend_error_noreturn(E_COMPILE_ERROR, "Property in interface cannot be final"); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 563928c9dbf59..162b7e84cefbe 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1116,6 +1116,14 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + FREE_OP_DATA(); + HANDLE_EXCEPTION(); + } + value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); do { @@ -1430,6 +1438,13 @@ ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + zend_pre_incdec_property_zval(prop, ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); @@ -1457,6 +1472,13 @@ ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + zend_post_incdec_property_zval(prop, ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); @@ -1836,18 +1858,29 @@ ZEND_VM_INLINE_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) { USE_OPLINE zval *prop; + zend_property_info *prop_info; SAVE_OPLINE(); prop = zend_fetch_static_property_address( - NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, + &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); prop = &EG(uninitialized_zval); + } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + if (Z_TYPE_P(prop) == IS_OBJECT) { + ZEND_VM_C_GOTO(copy_deref); + } else if (type != BP_VAR_UNSET || Z_TYPE_P(prop) != IS_UNDEF) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + } + prop = &EG(uninitialized_zval); } if (type == BP_VAR_R || type == BP_VAR_IS) { +ZEND_VM_C_LABEL(copy_deref): ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), prop); @@ -2893,6 +2926,14 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + FREE_OP_DATA(); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 97466dab76a94..902e254ff2424 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -783,6 +783,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { @@ -826,6 +834,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDL HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + zend_pre_incdec_property_zval(prop, ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); @@ -847,6 +862,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + zend_post_incdec_property_zval(prop, ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); @@ -858,18 +880,29 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ { USE_OPLINE zval *prop; + zend_property_info *prop_info; SAVE_OPLINE(); prop = zend_fetch_static_property_address( - NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, + &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); prop = &EG(uninitialized_zval); + } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + if (Z_TYPE_P(prop) == IS_OBJECT) { + goto copy_deref; + } else if (type != BP_VAR_UNSET || Z_TYPE_P(prop) != IS_UNDEF) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + } + prop = &EG(uninitialized_zval); } if (type == BP_VAR_R || type == BP_VAR_IS) { +copy_deref: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), prop); @@ -1105,6 +1138,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA HANDLE_EXCEPTION(); } + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { From c10afa9643cd4f9f11b63769e6cd18f01fcb9173 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 2 Apr 2025 17:33:02 +0200 Subject: [PATCH 257/503] Simplify curl gc handlers (#18227) Since these objects are final and have no dynamic properties, we don't have to build a property table. --- ext/curl/interface.c | 4 +++- ext/curl/multi.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 5be9327566b19..aebb336378bc0 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -546,7 +546,9 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) zend_get_gc_buffer_use(gc_buffer, table, n); - return zend_std_get_properties(object); + /* CurlHandle can never have properties as it's final and has strict-properties on. + * Avoid building a hash table. */ + return NULL; } zend_result curl_cast_object(zend_object *obj, zval *result, int type) diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 3d97b581be764..fd0a8316646f6 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -594,7 +594,9 @@ static HashTable *curl_multi_get_gc(zend_object *object, zval **table, int *n) zend_get_gc_buffer_use(gc_buffer, table, n); - return zend_std_get_properties(object); + /* CurlMultiHandle can never have properties as it's final and has strict-properties on. + * Avoid building a hash table. */ + return NULL; } static zend_object_handlers curl_multi_handlers; From 74720a22f332cb09435405d50c312413c86af45e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 23:36:57 +0100 Subject: [PATCH 258/503] Fix memory leak in openssl_sign() when passing invalid algorithm Closes GH-18185. --- NEWS | 4 ++++ ext/openssl/openssl.c | 1 + .../tests/openssl_sign_invalid_algorithm.phpt | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 ext/openssl/tests/openssl_sign_invalid_algorithm.phpt diff --git a/NEWS b/NEWS index 335903eee23c0..188c5a877968c 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage in gdImageCrop(). (David Carlier) +- OpenSSL: + . Fix memory leak in openssl_sign() when passing invalid algorithm. + (nielsdos) + - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index c5720ee97e38c..bd386dbe8ae7a 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -6959,6 +6959,7 @@ PHP_FUNCTION(openssl_sign) mdtype = php_openssl_get_evp_md_from_algo(method_long); } if (!mdtype) { + EVP_PKEY_free(pkey); php_error_docref(NULL, E_WARNING, "Unknown digest algorithm"); RETURN_FALSE; } diff --git a/ext/openssl/tests/openssl_sign_invalid_algorithm.phpt b/ext/openssl/tests/openssl_sign_invalid_algorithm.phpt new file mode 100644 index 0000000000000..c669a373a1079 --- /dev/null +++ b/ext/openssl/tests/openssl_sign_invalid_algorithm.phpt @@ -0,0 +1,18 @@ +--TEST-- +openssl_sign: invalid algorithm +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Warning: openssl_sign(): Unknown digest algorithm in %s on line %d From 0dc600c69aaf90361775c2d9c83094e324fae3d5 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 23:51:58 +0200 Subject: [PATCH 259/503] Fix openssl_random_pseudo_bytes() always setting strong_result to true This regressed in 62c7432f, prior to that commit the value was set to false in case random number generation failed, but now even if an exception is thrown it is set to true. This likely does not _really_ matter as the user will handle the exception, still the value in $strong_result is observable. --- ext/openssl/openssl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index bd386dbe8ae7a..9eb052335b8d5 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -7961,17 +7961,15 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) RETURN_THROWS(); } - if (zstrong_result_returned) { - ZEND_TRY_ASSIGN_REF_FALSE(zstrong_result_returned); - } - if ((buffer = php_openssl_random_pseudo_bytes(buffer_length))) { ZSTR_VAL(buffer)[buffer_length] = 0; RETVAL_NEW_STR(buffer); - } - if (zstrong_result_returned) { - ZEND_TRY_ASSIGN_REF_TRUE(zstrong_result_returned); + if (zstrong_result_returned) { + ZEND_TRY_ASSIGN_REF_TRUE(zstrong_result_returned); + } + } else if (zstrong_result_returned) { + ZEND_TRY_ASSIGN_REF_FALSE(zstrong_result_returned); } } /* }}} */ From 5e68671f88ef92f0612bfa3e2819e5107e624418 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 30 Mar 2025 23:54:56 +0200 Subject: [PATCH 260/503] Fix inverted call to php_openssl_store_errors() This calls php_openssl_store_errors() in the success path right now, change it to call php_openssl_store_errors() in the error path. --- ext/openssl/openssl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 9eb052335b8d5..bfbf51ff6442c 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -7940,11 +7940,10 @@ PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_le PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(buffer_length, length); PHP_OPENSSL_RAND_ADD_TIME(); if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) { + php_openssl_store_errors(); zend_string_release_ex(buffer, 0); zend_throw_exception(zend_ce_exception, "Error reading from source device", 0); return NULL; - } else { - php_openssl_store_errors(); } return buffer; From 8a1f6711bf75da789fbc23a63629d16a1925e252 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 1 Apr 2025 22:54:17 +0200 Subject: [PATCH 261/503] Fix resource leak in iptcembed() on error Closes GH-18225. --- NEWS | 1 + ext/standard/iptc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 188c5a877968c..92b199270cf4d 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,7 @@ PHP NEWS . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) . Fixed bug GH-18212 (fseek with SEEK_CUR whence value and negative offset leads to negative stream position). (David Carlier) + . Fix resource leak in iptcembed() on error. (nielsdos) 10 Apr 2025, PHP 8.3.20 diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c index e4dd38637570a..44dd33bab10ac 100644 --- a/ext/standard/iptc.c +++ b/ext/standard/iptc.c @@ -204,6 +204,7 @@ PHP_FUNCTION(iptcembed) if (spool < 2) { if (zend_fstat(fileno(fp), &sb) != 0) { + fclose(fp); RETURN_FALSE; } From ec35f534c63a37d21eb468e7c2c5778ab65307c1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 3 Apr 2025 12:46:22 +0200 Subject: [PATCH 262/503] [skip ci] Fix varying tmps count in nodiscard test --- Zend/tests/attributes/nodiscard/010.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/tests/attributes/nodiscard/010.phpt b/Zend/tests/attributes/nodiscard/010.phpt index 2de81d76aa6ae..f4f7b8488e98a 100644 --- a/Zend/tests/attributes/nodiscard/010.phpt +++ b/Zend/tests/attributes/nodiscard/010.phpt @@ -28,7 +28,7 @@ $obj = test(); ?> --EXPECTF-- $_main: - ; (lines=29, args=0, vars=3, tmps=1) + ; (lines=29, args=0, vars=3, tmps=%d) ; (after optimizer) ; %s 0000 INIT_FCALL 0 %d string("tmpfile") @@ -62,7 +62,7 @@ $_main: 0028 RETURN int(1) test: - ; (lines=3, args=0, vars=0, tmps=1) + ; (lines=3, args=0, vars=0, tmps=%d) ; (after optimizer) ; %s 0000 V0 = NEW 0 string("stdClass") From 8f67130e9e80802dd757c6c2e2e16565efc8c597 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 3 Apr 2025 12:58:55 +0200 Subject: [PATCH 263/503] [skip ci] Move opcode dumping test to ext/opcache/tests This test breaks with file cache, because the file isn't compiled. Tests in ext/opcache/tests are automatically skipped with file cache, hence circumventing this issue. --- .../nodiscard/010.phpt => ext/opcache/tests/nodiscard_001.phpt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Zend/tests/attributes/nodiscard/010.phpt => ext/opcache/tests/nodiscard_001.phpt (100%) diff --git a/Zend/tests/attributes/nodiscard/010.phpt b/ext/opcache/tests/nodiscard_001.phpt similarity index 100% rename from Zend/tests/attributes/nodiscard/010.phpt rename to ext/opcache/tests/nodiscard_001.phpt From 7a3383b482af333c03aca7d52a2012857840e746 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 3 Apr 2025 13:01:59 +0200 Subject: [PATCH 264/503] [skip ci] Restrict on-push freebsd build to main repo The same applies to all other push jobs, it was just forgotten here. --- .github/workflows/push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index ddc90935018ba..214798af62b5c 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -171,6 +171,7 @@ jobs: - name: Test run: .github/scripts/windows/test.bat FREEBSD: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' name: FREEBSD runs-on: ubuntu-latest steps: From 3d41cb012a536ace5c523f3629cfcc56dabbe4b6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 30 Mar 2025 17:49:32 +0100 Subject: [PATCH 265/503] ext/fileinfo: Use magic_setflags() directly The only way this function returns -1 is if: > magic_setflags() returns -1 on systems that don't support utime(3), or utimes(2) when MAGIC_PRESERVE_ATIME is set. This is extremely unlikely and if this would happen we currently have a return type violation. --- ext/fileinfo/fileinfo.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 52172dfbd692d..4311afff1802d 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -94,14 +94,6 @@ PHP_FILEINFO_API zend_object *finfo_objects_new(zend_class_entry *class_type) } /* }}} */ -#define FINFO_SET_OPTION(magic, options) \ - if (magic_setflags(magic, options) == -1) { \ - php_error_docref(NULL, E_WARNING, "Failed to set option '" ZEND_LONG_FMT "' %d:%s", \ - options, magic_errno(magic), magic_error(magic)); \ - RETURN_FALSE; \ - } -/* }}} */ - /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(finfo) { @@ -276,7 +268,9 @@ PHP_FUNCTION(finfo_set_flags) } FILEINFO_FROM_OBJECT(finfo, self); - FINFO_SET_OPTION(finfo->magic, options) + /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME + * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ + magic_setflags(finfo->magic, options); finfo->options = options; RETURN_TRUE; @@ -337,7 +331,9 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime /* Set options for the current file/buffer. */ if (options) { - FINFO_SET_OPTION(magic, options) + /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME + * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ + magic_setflags(magic, options); } switch (mode) { @@ -436,9 +432,8 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime /* Restore options */ if (options) { - FINFO_SET_OPTION(magic, finfo->options) + magic_setflags(magic, finfo->options); } - return; } /* }}} */ From fabee4e2442c48fbb482329d0e87dc1e7bb2fc2e Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 30 Mar 2025 18:11:42 +0100 Subject: [PATCH 266/503] ext/fileinfo: Separate implementations of functions Instead of relying on a "god" function --- UPGRADING | 6 + ext/fileinfo/fileinfo.c | 293 ++++++++++++----------- ext/fileinfo/tests/finfo_file_001.phpt | 2 +- ext/fileinfo/tests/finfo_file_basic.phpt | 2 +- 4 files changed, 161 insertions(+), 142 deletions(-) diff --git a/UPGRADING b/UPGRADING index 9dfc984f8917d..082439b9264c8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -45,6 +45,12 @@ PHP 8.5 UPGRADE NOTES change, but should closer match user expectations, demonstrated by GH-15753 and GH-16198. +- FileInfo: + . finfo_file() and finfo::file() now throws a ValueError instead of a + TypeError when $filename contains nul bytes. + This aligns the type of Error thrown to be consistent with the rest of + the language. + - Intl: . The extension now requires at least ICU 57.1. diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 4311afff1802d..d3680c5755f25 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -277,57 +277,73 @@ PHP_FUNCTION(finfo_set_flags) } /* }}} */ -#define FILEINFO_MODE_BUFFER 0 -#define FILEINFO_MODE_STREAM 1 -#define FILEINFO_MODE_FILE 2 - -static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */ +static const char* php_fileinfo_from_path(struct magic_set *magic, const zend_string *path, php_stream_context *context) { - zend_long options = 0; - char *ret_val = NULL, *buffer = NULL; - size_t buffer_len; - php_fileinfo *finfo = NULL; - zval *zcontext = NULL; - zval *what; - char mime_directory[] = "directory"; - struct magic_set *magic = NULL; + ZEND_ASSERT(magic != NULL); + ZEND_ASSERT(path); + ZEND_ASSERT(ZSTR_LEN(path) != 0); + ZEND_ASSERT(!zend_str_has_nul_byte(path)); + ZEND_ASSERT(context != NULL); + + /* determine if the file is a local file or remote URL */ + const char *dummy; + php_stream_statbuf ssb; + + const php_stream_wrapper *wrap = php_stream_locate_url_wrapper(ZSTR_VAL(path), &dummy, 0); + if (UNEXPECTED(wrap == NULL)) { + return NULL; + } - if (mimetype_emu) { +#ifdef PHP_WIN32 + if (php_stream_stat_path_ex(ZSTR_VAL(path), 0, &ssb, context) == SUCCESS) { + if (ssb.sb.st_mode & S_IFDIR) { + return "directory"; + } + } +#endif - /* mime_content_type(..) emulation */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &what) == FAILURE) { - RETURN_THROWS(); + php_stream *stream = php_stream_open_wrapper_ex(ZSTR_VAL(path), "rb", REPORT_ERRORS, NULL, context); + if (!stream) { + return NULL; + } + + const char *ret_val = NULL; + if (php_stream_stat(stream, &ssb) == SUCCESS) { + if (ssb.sb.st_mode & S_IFDIR) { + ret_val = "directory"; + } else { + ret_val = magic_stream(magic, stream); + if (UNEXPECTED(ret_val == NULL)) { + php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic)); + } } + } - switch (Z_TYPE_P(what)) { - case IS_STRING: - buffer = Z_STRVAL_P(what); - buffer_len = Z_STRLEN_P(what); - mode = FILEINFO_MODE_FILE; - break; + php_stream_close(stream); - case IS_RESOURCE: - mode = FILEINFO_MODE_STREAM; - break; + return ret_val; +} - default: - zend_argument_type_error(1, "must be of type resource|string, %s given", zend_zval_value_name(what)); - RETURN_THROWS(); - } +/* Return information about a file. */ +PHP_FUNCTION(finfo_file) +{ + zval *self; + zend_string *path = NULL; + zend_long options = 0; + zval *zcontext = NULL; + php_fileinfo *finfo = NULL; - magic = magic_open(MAGIC_MIME_TYPE); - if (magic_load(magic, NULL) == -1) { - php_error_docref(NULL, E_WARNING, "Failed to load magic database"); - goto common; - } - } else { - zval *self; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|lr!", &self, finfo_class_entry, &buffer, &buffer_len, &options, &zcontext) == FAILURE) { - RETURN_THROWS(); - } - FILEINFO_FROM_OBJECT(finfo, self); - magic = finfo->magic; + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OP|lr!", &self, finfo_class_entry, &path, &options, &zcontext) == FAILURE) { + RETURN_THROWS(); + } + FILEINFO_FROM_OBJECT(finfo, self); + struct magic_set *magic = finfo->magic; + + if (UNEXPECTED(ZSTR_LEN(path) == 0)) { + zend_argument_must_not_be_empty_error(2); + RETURN_THROWS(); } + php_stream_context *context = php_stream_context_from_zval(zcontext, false); /* Set options for the current file/buffer. */ if (options) { @@ -336,124 +352,121 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime magic_setflags(magic, options); } - switch (mode) { - case FILEINFO_MODE_BUFFER: - { - ret_val = (char *) magic_buffer(magic, buffer, buffer_len); - break; - } - - case FILEINFO_MODE_STREAM: - { - php_stream *stream; - zend_off_t streampos; - - php_stream_from_zval_no_verify(stream, what); - if (!stream) { - goto common; - } - - streampos = php_stream_tell(stream); /* remember stream position for restoration */ - php_stream_seek(stream, 0, SEEK_SET); + const char *ret_val = php_fileinfo_from_path(magic, path, context); + /* Restore options */ + if (options) { + magic_setflags(magic, finfo->options); + } - ret_val = (char *) magic_stream(magic, stream); + if (UNEXPECTED(ret_val == NULL)) { + RETURN_FALSE; + } else { + RETURN_STRING(ret_val); + } +} - php_stream_seek(stream, streampos, SEEK_SET); - break; - } +/* Return information about a string buffer. */ +PHP_FUNCTION(finfo_buffer) +{ + zval *self; + zend_string *buffer = NULL; + zend_long options = 0; + zval *dummy_context = NULL; + php_fileinfo *finfo = NULL; - case FILEINFO_MODE_FILE: - { - /* determine if the file is a local file or remote URL */ - const char *tmp2; - php_stream_wrapper *wrap; - php_stream_statbuf ssb; - - // Implementation is used for both finfo_file() and mimetype_emu() - int buffer_param_num = (mimetype_emu ? 1 : 2); - if (buffer == NULL || buffer_len == 0) { - zend_argument_must_not_be_empty_error(buffer_param_num); - goto clean; - } - if (CHECK_NULL_PATH(buffer, buffer_len)) { - zend_argument_type_error(buffer_param_num, "must not contain any null bytes"); - goto clean; - } + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OS|lr!", &self, finfo_class_entry, &buffer, &options, &dummy_context) == FAILURE) { + RETURN_THROWS(); + } + FILEINFO_FROM_OBJECT(finfo, self); + struct magic_set *magic = finfo->magic; - wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0); + /* Set options for the current file/buffer. */ + if (options) { + magic_setflags(magic, options); + } - if (wrap) { - php_stream *stream; - php_stream_context *context = php_stream_context_from_zval(zcontext, 0); + const char *ret_val = magic_buffer(magic, ZSTR_VAL(buffer), ZSTR_LEN(buffer)); -#ifdef PHP_WIN32 - if (php_stream_stat_path_ex(buffer, 0, &ssb, context) == SUCCESS) { - if (ssb.sb.st_mode & S_IFDIR) { - ret_val = mime_directory; - goto common; - } - } -#endif + /* Restore options */ + if (options) { + magic_setflags(magic, finfo->options); + } - stream = php_stream_open_wrapper_ex(buffer, "rb", REPORT_ERRORS, NULL, context); + if (UNEXPECTED(ret_val == NULL)) { + php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic)); + RETURN_FALSE; + } else { + RETURN_STRING(ret_val); + } +} - if (!stream) { - RETVAL_FALSE; - goto clean; - } +/* Return content-type for file */ +PHP_FUNCTION(mime_content_type) +{ + zval *path_or_stream; + const zend_string *path = NULL; + php_stream *stream = NULL; + struct magic_set *magic = NULL; - if (php_stream_stat(stream, &ssb) == SUCCESS) { - if (ssb.sb.st_mode & S_IFDIR) { - ret_val = mime_directory; - } else { - ret_val = (char *)magic_stream(magic, stream); - } - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &path_or_stream) == FAILURE) { + RETURN_THROWS(); + } - php_stream_close(stream); + switch (Z_TYPE_P(path_or_stream)) { + case IS_STRING: + path = Z_STR_P(path_or_stream); + if (UNEXPECTED(ZSTR_LEN(path) == 0)) { + zend_argument_must_not_be_empty_error(1); + RETURN_THROWS(); + } + if (UNEXPECTED(zend_str_has_nul_byte(path))) { + zend_argument_type_error(1, "must not contain any null bytes"); + RETURN_THROWS(); } break; - } - EMPTY_SWITCH_DEFAULT_CASE() + + case IS_RESOURCE: + php_stream_from_zval(stream, path_or_stream); + break; + + default: + zend_argument_type_error(1, "must be of type resource|string, %s given", zend_zval_value_name(path_or_stream)); + RETURN_THROWS(); } -common: - if (ret_val) { - RETVAL_STRING(ret_val); - } else { - php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic)); - RETVAL_FALSE; + magic = magic_open(MAGIC_MIME_TYPE); + if (UNEXPECTED(magic == NULL)) { + php_error_docref(NULL, E_WARNING, "Failed to load magic database"); + RETURN_FALSE; } -clean: - if (mimetype_emu) { + if (UNEXPECTED(magic_load(magic, NULL) == -1)) { + php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic)); magic_close(magic); + RETURN_FALSE; } - /* Restore options */ - if (options) { - magic_setflags(magic, finfo->options); - } -} -/* }}} */ + const char *ret_val; + if (path) { + php_stream_context *context = php_stream_context_get_default(false); + ret_val = php_fileinfo_from_path(magic, path, context); + } else { + /* remember stream position for restoration */ + zend_off_t current_stream_pos = php_stream_tell(stream); + php_stream_seek(stream, 0, SEEK_SET); -/* {{{ Return information about a file. */ -PHP_FUNCTION(finfo_file) -{ - _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_FILE, 0); -} -/* }}} */ + ret_val = magic_stream(magic, stream); + if (UNEXPECTED(ret_val == NULL)) { + php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic)); + } -/* {{{ Return information about a string buffer. */ -PHP_FUNCTION(finfo_buffer) -{ - _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_BUFFER, 0); -} -/* }}} */ + php_stream_seek(stream, current_stream_pos, SEEK_SET); + } -/* {{{ Return content-type for file */ -PHP_FUNCTION(mime_content_type) -{ - _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1, 1); + if (UNEXPECTED(ret_val == NULL)) { + RETVAL_FALSE; + } else { + RETVAL_STRING(ret_val); + } + magic_close(magic); } -/* }}} */ diff --git a/ext/fileinfo/tests/finfo_file_001.phpt b/ext/fileinfo/tests/finfo_file_001.phpt index 1e31b8ad1c049..737b8db53ff77 100644 --- a/ext/fileinfo/tests/finfo_file_001.phpt +++ b/ext/fileinfo/tests/finfo_file_001.phpt @@ -8,7 +8,7 @@ fileinfo $fp = finfo_open(); try { var_dump(finfo_file($fp, "\0")); -} catch (\TypeError $e) { +} catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } try { diff --git a/ext/fileinfo/tests/finfo_file_basic.phpt b/ext/fileinfo/tests/finfo_file_basic.phpt index e6f2b1e8570d5..4545a3063a7fe 100644 --- a/ext/fileinfo/tests/finfo_file_basic.phpt +++ b/ext/fileinfo/tests/finfo_file_basic.phpt @@ -15,7 +15,7 @@ var_dump( finfo_file( $finfo, __FILE__, FILEINFO_CONTINUE ) ); var_dump( finfo_file( $finfo, $magicFile ) ); try { var_dump( finfo_file( $finfo, $magicFile.chr(0).$magicFile) ); -} catch (\TypeError $e) { +} catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } From 7fb8db014e4992b97d2c215255cbe23421ff8b73 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 19:19:36 +0100 Subject: [PATCH 267/503] ext/ftp: Voidify ftp_close() --- ext/ftp/ftp.c | 6 ++---- ext/ftp/ftp.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 3dc401a4bffbb..970b90e9a484c 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -161,11 +161,10 @@ ftp_open(const char *host, short port, zend_long timeout_sec) /* }}} */ /* {{{ ftp_close */ -ftpbuf_t* -ftp_close(ftpbuf_t *ftp) +void ftp_close(ftpbuf_t *ftp) { if (ftp == NULL) { - return NULL; + return; } #ifdef HAVE_FTP_SSL if (ftp->last_ssl_session) { @@ -186,7 +185,6 @@ ftp_close(ftpbuf_t *ftp) } ftp_gc(ftp); efree(ftp); - return NULL; } /* }}} */ diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 94abc588ca857..7b51734579de5 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -103,7 +103,7 @@ int ftp_quit(ftpbuf_t *ftp); void ftp_gc(ftpbuf_t *ftp); /* close the FTP connection and return NULL */ -ftpbuf_t* ftp_close(ftpbuf_t *ftp); +void ftp_close(ftpbuf_t *ftp); /* logs into the FTP server, returns true on success, false on error */ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len); From 51fa97fb442c6ab40630390b91bec054a20fa6a7 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 19:30:45 +0100 Subject: [PATCH 268/503] ext/ftp: Normalize coding style --- ext/ftp/ftp.c | 284 +++++++++++++------------------------------------- ext/ftp/ftp.h | 63 ++++++----- 2 files changed, 101 insertions(+), 246 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 970b90e9a484c..60ef58347163e 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -68,41 +68,37 @@ * it sends the string "cmd args\r\n" if args is non-null, or * "cmd\r\n" if args is null */ -static int ftp_putcmd( ftpbuf_t *ftp, - const char *cmd, - const size_t cmd_len, - const char *args, - const size_t args_len); +static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len); /* wrapper around send/recv to handle timeouts */ -static int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); -static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); -static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen); +static int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); +static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); +static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen); /* reads a line the socket , returns true on success, false on error */ -static int ftp_readline(ftpbuf_t *ftp); +static int ftp_readline(ftpbuf_t *ftp); /* reads an ftp response, returns true on success, false on error */ -static int ftp_getresp(ftpbuf_t *ftp); +static int ftp_getresp(ftpbuf_t *ftp); /* sets the ftp transfer type */ -static int ftp_type(ftpbuf_t *ftp, ftptype_t type); +static int ftp_type(ftpbuf_t *ftp, ftptype_t type); /* opens up a data stream */ -static databuf_t* ftp_getdata(ftpbuf_t *ftp); +static databuf_t* ftp_getdata(ftpbuf_t *ftp); /* accepts the data connection, returns updated data buffer */ -static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp); +static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp); /* closes the data connection, no-op if already closed */ -static void data_close(ftpbuf_t *ftp); +static void data_close(ftpbuf_t *ftp); /* generic file lister */ -static char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len); +static char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len); #ifdef HAVE_FTP_SSL /* shuts down a TLS/SSL connection */ -static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle); +static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle); #endif /* IP and port conversion box */ @@ -112,9 +108,7 @@ union ipbox { unsigned char c[8]; }; -/* {{{ ftp_open */ -ftpbuf_t* -ftp_open(const char *host, short port, zend_long timeout_sec) +ftpbuf_t* ftp_open(const char *host, short port, zend_long timeout_sec) { ftpbuf_t *ftp; socklen_t size; @@ -158,9 +152,7 @@ ftp_open(const char *host, short port, zend_long timeout_sec) efree(ftp); return NULL; } -/* }}} */ -/* {{{ ftp_close */ void ftp_close(ftpbuf_t *ftp) { if (ftp == NULL) { @@ -186,11 +178,8 @@ void ftp_close(ftpbuf_t *ftp) ftp_gc(ftp); efree(ftp); } -/* }}} */ -/* {{{ ftp_gc */ -void -ftp_gc(ftpbuf_t *ftp) +void ftp_gc(ftpbuf_t *ftp) { if (ftp == NULL) { return; @@ -204,11 +193,8 @@ ftp_gc(ftpbuf_t *ftp) ftp->syst = NULL; } } -/* }}} */ -/* {{{ ftp_quit */ -int -ftp_quit(ftpbuf_t *ftp) +int ftp_quit(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; @@ -228,7 +214,6 @@ ftp_quit(ftpbuf_t *ftp) return 1; } -/* }}} */ #ifdef HAVE_FTP_SSL static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) @@ -246,9 +231,7 @@ static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) } #endif -/* {{{ ftp_login */ -int -ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len) +int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len) { #ifdef HAVE_FTP_SSL SSL_CTX *ctx = NULL; @@ -393,11 +376,8 @@ ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pa } return (ftp->resp == 230); } -/* }}} */ -/* {{{ ftp_reinit */ -int -ftp_reinit(ftpbuf_t *ftp) +int ftp_reinit(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; @@ -416,11 +396,8 @@ ftp_reinit(ftpbuf_t *ftp) return 1; } -/* }}} */ -/* {{{ ftp_syst */ -const char* -ftp_syst(ftpbuf_t *ftp) +const char* ftp_syst(ftpbuf_t *ftp) { char *syst, *end; @@ -451,11 +428,8 @@ ftp_syst(ftpbuf_t *ftp) } return ftp->syst; } -/* }}} */ -/* {{{ ftp_pwd */ -const char* -ftp_pwd(ftpbuf_t *ftp) +const char* ftp_pwd(ftpbuf_t *ftp) { char *pwd, *end; @@ -484,11 +458,8 @@ ftp_pwd(ftpbuf_t *ftp) return ftp->pwd; } -/* }}} */ -/* {{{ ftp_exec */ -int -ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) +int ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) { if (ftp == NULL) { return 0; @@ -502,11 +473,8 @@ ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) return 1; } -/* }}} */ -/* {{{ ftp_raw */ -void -ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value) +void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value) { if (ftp == NULL || cmd == NULL) { RETURN_NULL(); @@ -522,11 +490,8 @@ ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value } } } -/* }}} */ -/* {{{ ftp_chdir */ -int -ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) +int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) { if (ftp == NULL) { return 0; @@ -545,11 +510,8 @@ ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) } return 1; } -/* }}} */ -/* {{{ ftp_cdup */ -int -ftp_cdup(ftpbuf_t *ftp) +int ftp_cdup(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; @@ -568,11 +530,8 @@ ftp_cdup(ftpbuf_t *ftp) } return 1; } -/* }}} */ -/* {{{ ftp_mkdir */ -zend_string* -ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) +zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) { char *mkd, *end; zend_string *ret; @@ -599,11 +558,8 @@ ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) return ret; } -/* }}} */ -/* {{{ ftp_rmdir */ -int -ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) +int ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) { if (ftp == NULL) { return 0; @@ -616,11 +572,8 @@ ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) } return 1; } -/* }}} */ -/* {{{ ftp_chmod */ -int -ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) +int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) { char *buffer; size_t buffer_len; @@ -648,11 +601,8 @@ ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filenam return 1; } -/* }}} */ -/* {{{ ftp_alloc */ -int -ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) +int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) { char buffer[64]; int buffer_len; @@ -685,36 +635,24 @@ ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) return 1; } -/* }}} */ -/* {{{ ftp_nlist */ -char** -ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len) +char** ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len) { return ftp_genlist(ftp, "NLST", sizeof("NLST")-1, path, path_len); } -/* }}} */ -/* {{{ ftp_list */ -char** -ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive) +char** ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive) { return ftp_genlist(ftp, ((recursive) ? "LIST -R" : "LIST"), ((recursive) ? sizeof("LIST -R")-1 : sizeof("LIST")-1), path, path_len); } -/* }}} */ -/* {{{ ftp_mlsd */ -char** -ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len) +char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len) { return ftp_genlist(ftp, "MLSD", sizeof("MLSD")-1, path, path_len); } -/* }}} */ - -/* {{{ ftp_mlsd_parse_line */ -int -ftp_mlsd_parse_line(HashTable *ht, const char *input) { +int ftp_mlsd_parse_line(HashTable *ht, const char *input) +{ zval zstr; const char *end = input + strlen(input); @@ -753,11 +691,8 @@ ftp_mlsd_parse_line(HashTable *ht, const char *input) { return SUCCESS; } -/* }}} */ -/* {{{ ftp_type */ -int -ftp_type(ftpbuf_t *ftp, ftptype_t type) +int ftp_type(ftpbuf_t *ftp, ftptype_t type) { const char *typechar; @@ -784,11 +719,8 @@ ftp_type(ftpbuf_t *ftp, ftptype_t type) return 1; } -/* }}} */ -/* {{{ ftp_pasv */ -int -ftp_pasv(ftpbuf_t *ftp, int pasv) +int ftp_pasv(ftpbuf_t *ftp, int pasv) { char *ptr; union ipbox ipbox; @@ -877,11 +809,8 @@ ftp_pasv(ftpbuf_t *ftp, int pasv) return 1; } -/* }}} */ -/* {{{ ftp_get */ -int -ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) +int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) { databuf_t *data = NULL; size_t rcvd; @@ -970,7 +899,6 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t pat data_close(ftp); return 0; } -/* }}} */ static zend_result ftp_send_stream_to_data_socket(ftpbuf_t *ftp, databuf_t *data, php_stream *instream, ftptype_t type, bool send_once_and_return) { @@ -1045,9 +973,7 @@ static zend_result ftp_send_stream_to_data_socket(ftpbuf_t *ftp, databuf_t *data return SUCCESS; } -/* {{{ ftp_put */ -int -ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) +int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) { databuf_t *data = NULL; char arg[MAX_LENGTH_OF_LONG]; @@ -1100,14 +1026,10 @@ ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *inst data_close(ftp); return 0; } -/* }}} */ - -/* {{{ ftp_append */ -int -ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type) +int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type) { - databuf_t *data = NULL; + databuf_t *data = NULL; if (ftp == NULL) { return 0; @@ -1144,11 +1066,8 @@ ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *i data_close(ftp); return 0; } -/* }}} */ -/* {{{ ftp_size */ -zend_long -ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len) +zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len) { if (ftp == NULL) { return -1; @@ -1164,11 +1083,8 @@ ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len) } return ZEND_ATOL(ftp->inbuf); } -/* }}} */ -/* {{{ ftp_mdtm */ -time_t -ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len) +time_t ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len) { time_t stamp; struct tm *gmt, tmbuf; @@ -1211,11 +1127,8 @@ ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len) return stamp; } -/* }}} */ -/* {{{ ftp_delete */ -int -ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len) +int ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len) { if (ftp == NULL) { return 0; @@ -1229,11 +1142,8 @@ ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len) return 1; } -/* }}} */ -/* {{{ ftp_rename */ -int -ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len) +int ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len) { if (ftp == NULL) { return 0; @@ -1252,11 +1162,8 @@ ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *des } return 1; } -/* }}} */ -/* {{{ ftp_site */ -int -ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) +int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) { if (ftp == NULL) { return 0; @@ -1270,16 +1177,12 @@ ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) return 1; } -/* }}} */ /* static functions */ - -/* {{{ ftp_putcmd */ -int -ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) +int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) { - int size; - char *data; + int size; + char *data; if (strpbrk(cmd, "\r\n")) { return 0; @@ -1313,14 +1216,11 @@ ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *arg } return 1; } -/* }}} */ -/* {{{ ftp_readline */ -int -ftp_readline(ftpbuf_t *ftp) +int ftp_readline(ftpbuf_t *ftp) { - long size, rcvd; - char *data, *eol; + long size, rcvd; + char *data, *eol; /* shift the extra to the front */ size = FTP_BUFSIZE; @@ -1366,11 +1266,8 @@ ftp_readline(ftpbuf_t *ftp) *data = 0; return 0; } -/* }}} */ -/* {{{ ftp_getresp */ -int -ftp_getresp(ftpbuf_t *ftp) +int ftp_getresp(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; @@ -1403,7 +1300,6 @@ ftp_getresp(ftpbuf_t *ftp) } return 1; } -/* }}} */ static ssize_t my_send_wrapper_with_restart(php_socket_t fd, const void *buf, size_t size, int flags) { ssize_t n; @@ -1504,9 +1400,7 @@ static int my_poll(php_socket_t fd, int events, int timeout) { return n; } -/* {{{ my_send */ -int -my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) +int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { zend_long size, sent; int n; @@ -1539,13 +1433,10 @@ my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) return len; } -/* }}} */ -/* {{{ my_recv */ -int -my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) +int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { - int n, nr_bytes; + int n, nr_bytes; #ifdef HAVE_FTP_SSL int err; bool retry = 0; @@ -1618,13 +1509,10 @@ my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) #endif return (nr_bytes); } -/* }}} */ -/* {{{ data_available */ -int -data_available(ftpbuf_t *ftp, php_socket_t s) +int data_available(ftpbuf_t *ftp, php_socket_t s) { - int n; + int n; n = my_poll(s, PHP_POLLREADABLE, 1000); if (n < 1) { @@ -1642,12 +1530,10 @@ data_available(ftpbuf_t *ftp, php_socket_t s) return 1; } -/* }}} */ -/* {{{ data_writeable */ -int -data_writeable(ftpbuf_t *ftp, php_socket_t s) + +int data_writeable(ftpbuf_t *ftp, php_socket_t s) { - int n; + int n; n = my_poll(s, POLLOUT, 1000); if (n < 1) { @@ -1665,13 +1551,10 @@ data_writeable(ftpbuf_t *ftp, php_socket_t s) return 1; } -/* }}} */ -/* {{{ my_accept */ -int -my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) +int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) { - int n; + int n; n = my_poll(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { @@ -1689,11 +1572,8 @@ my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrl return accept(s, addr, addrlen); } -/* }}} */ -/* {{{ ftp_getdata */ -databuf_t* -ftp_getdata(ftpbuf_t *ftp) +databuf_t* ftp_getdata(ftpbuf_t *ftp) { int fd = -1; databuf_t *data; @@ -1822,14 +1702,11 @@ ftp_getdata(ftpbuf_t *ftp) efree(data); return NULL; } -/* }}} */ -/* {{{ data_accept */ -databuf_t* -data_accept(databuf_t *data, ftpbuf_t *ftp) +databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp) { php_sockaddr_storage addr; - socklen_t size; + socklen_t size; #ifdef HAVE_FTP_SSL SSL_CTX *ctx; @@ -1935,9 +1812,7 @@ data_accept(databuf_t *data, ftpbuf_t *ftp) return data; } -/* }}} */ -/* {{{ ftp_ssl_shutdown */ #ifdef HAVE_FTP_SSL static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) { /* In TLS 1.3 it's common to receive session tickets after the handshake has completed. We need to train @@ -1998,9 +1873,7 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) { (void)SSL_free(ssl_handle); } #endif -/* }}} */ -/* {{{ data_close */ void data_close(ftpbuf_t *ftp) { ZEND_ASSERT(ftp != NULL); @@ -2031,11 +1904,8 @@ void data_close(ftpbuf_t *ftp) ftp->data = NULL; efree(data); } -/* }}} */ -/* {{{ ftp_genlist */ -char** -ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len) +char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len) { php_stream *tmpstream = NULL; databuf_t *data = NULL; @@ -2135,14 +2005,11 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *pa efree(ret); return NULL; } -/* }}} */ -/* {{{ ftp_nb_get */ -int -ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) +int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) { - databuf_t *data = NULL; - char arg[MAX_LENGTH_OF_LONG]; + databuf_t *data = NULL; + char arg[MAX_LENGTH_OF_LONG]; if (ftp == NULL) { return PHP_FTP_FAILED; @@ -2201,11 +2068,8 @@ ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t data_close(ftp); return PHP_FTP_FAILED; } -/* }}} */ -/* {{{ ftp_nb_continue_read */ -int -ftp_nb_continue_read(ftpbuf_t *ftp) +int ftp_nb_continue_read(ftpbuf_t *ftp) { databuf_t *data = NULL; char *ptr; @@ -2263,11 +2127,8 @@ ftp_nb_continue_read(ftpbuf_t *ftp) data_close(ftp); return PHP_FTP_FAILED; } -/* }}} */ -/* {{{ ftp_nb_put */ -int -ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) +int ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) { databuf_t *data = NULL; char arg[MAX_LENGTH_OF_LONG]; @@ -2315,12 +2176,8 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *i data_close(ftp); return PHP_FTP_FAILED; } -/* }}} */ - -/* {{{ ftp_nb_continue_write */ -int -ftp_nb_continue_write(ftpbuf_t *ftp) +int ftp_nb_continue_write(ftpbuf_t *ftp) { /* check if we can write more data */ if (!data_writeable(ftp, ftp->data->fd)) { @@ -2347,4 +2204,3 @@ ftp_nb_continue_write(ftpbuf_t *ftp) ftp->nb = 0; return PHP_FTP_FAILED; } -/* }}} */ diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 7b51734579de5..bcd69059cbc86 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -92,42 +92,42 @@ typedef struct ftpbuf /* open a FTP connection, returns ftpbuf (NULL on error) * port is the ftp port in network byte order, or 0 for the default */ -ftpbuf_t* ftp_open(const char *host, short port, zend_long timeout_sec); +ftpbuf_t* ftp_open(const char *host, short port, zend_long timeout_sec); /* quits from the ftp session (it still needs to be closed) * return true on success, false on error */ -int ftp_quit(ftpbuf_t *ftp); +int ftp_quit(ftpbuf_t *ftp); /* frees up any cached data held in the ftp buffer */ -void ftp_gc(ftpbuf_t *ftp); +void ftp_gc(ftpbuf_t *ftp); /* close the FTP connection and return NULL */ void ftp_close(ftpbuf_t *ftp); /* logs into the FTP server, returns true on success, false on error */ -int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len); +int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len); /* reinitializes the connection, returns true on success, false on error */ -int ftp_reinit(ftpbuf_t *ftp); +int ftp_reinit(ftpbuf_t *ftp); /* returns the remote system type (NULL on error) */ -const char* ftp_syst(ftpbuf_t *ftp); +const char* ftp_syst(ftpbuf_t *ftp); /* returns the present working directory (NULL on error) */ -const char* ftp_pwd(ftpbuf_t *ftp); +const char* ftp_pwd(ftpbuf_t *ftp); /* exec a command [special features], return true on success, false on error */ -int ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); +int ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); /* send a raw ftp command, return response as a hashtable, NULL on error */ -void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value); +void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value); /* changes directories, return true on success, false on error */ -int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); +int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* changes to parent directory, return true on success, false on error */ -int ftp_cdup(ftpbuf_t *ftp); +int ftp_cdup(ftpbuf_t *ftp); /* creates a directory, return the directory name on success, NULL on error. * the return value must be freed @@ -135,95 +135,94 @@ int ftp_cdup(ftpbuf_t *ftp); zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* removes a directory, return true on success, false on error */ -int ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); +int ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* Set permissions on a file */ -int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); +int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); /* Allocate space on remote server with ALLO command * Many servers will respond with 202 Allocation not necessary, * however some servers will not accept STOR or APPE until ALLO is confirmed. * If response is passed, it is estrdup()ed from ftp->inbuf and must be freed * or assigned to a zval returned to the user */ -int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response); +int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response); /* returns a NULL-terminated array of filenames in the given path * or NULL on error. the return array must be freed (but don't * free the array elements) */ -char** ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len); +char** ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len); /* returns a NULL-terminated array of lines returned by the ftp * LIST command for the given path or NULL on error. the return * array must be freed (but don't * free the array elements) */ -char** ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive); +char** ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive); /* populates a hashtable with the facts contained in one line of * an MLSD response. */ -int ftp_mlsd_parse_line(HashTable *ht, const char *input); +int ftp_mlsd_parse_line(HashTable *ht, const char *input); /* returns a NULL-terminated array of lines returned by the ftp * MLSD command for the given path or NULL on error. the return * array must be freed (but don't * free the array elements) */ -char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len); +char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len); /* switches passive mode on or off * returns true on success, false on error */ -int ftp_pasv(ftpbuf_t *ftp, int pasv); +int ftp_pasv(ftpbuf_t *ftp, int pasv); /* retrieves a file and saves its contents to outfp * returns true on success, false on error */ -int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); +int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); /* stores the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ -int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); +int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); /* append the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ -int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type); +int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type); /* returns the size of the given file, or -1 on error */ -zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len); +zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len); /* returns the last modified time of the given file, or -1 on error */ -time_t ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len); +time_t ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len); /* renames a file on the server */ -int ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len); +int ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len); /* deletes the file from the server */ -int ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len); +int ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len); /* sends a SITE command to the server */ -int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); +int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); /* retrieves part of a file and saves its contents to outfp * returns true on success, false on error */ -int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); +int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); /* stores the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ -int ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); +int ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); /* continues a previous nb_(f)get command */ -int ftp_nb_continue_read(ftpbuf_t *ftp); +int ftp_nb_continue_read(ftpbuf_t *ftp); /* continues a previous nb_(f)put command */ -int ftp_nb_continue_write(ftpbuf_t *ftp); - +int ftp_nb_continue_write(ftpbuf_t *ftp); #endif From 114a8ffb9da006f58776c9978b89d2bee9f6f58d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 19:39:34 +0100 Subject: [PATCH 269/503] ext/ftp: Mark static functions as such Removing missleading comment --- ext/ftp/ftp.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 60ef58347163e..c707a784a1194 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -692,7 +692,7 @@ int ftp_mlsd_parse_line(HashTable *ht, const char *input) return SUCCESS; } -int ftp_type(ftpbuf_t *ftp, ftptype_t type) +static int ftp_type(ftpbuf_t *ftp, ftptype_t type) { const char *typechar; @@ -1178,8 +1178,7 @@ int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) return 1; } -/* static functions */ -int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) +static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) { int size; char *data; @@ -1217,7 +1216,7 @@ int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char return 1; } -int ftp_readline(ftpbuf_t *ftp) +static int ftp_readline(ftpbuf_t *ftp) { long size, rcvd; char *data, *eol; @@ -1267,7 +1266,7 @@ int ftp_readline(ftpbuf_t *ftp) return 0; } -int ftp_getresp(ftpbuf_t *ftp) +static int ftp_getresp(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; @@ -1317,7 +1316,7 @@ static ssize_t my_recv_wrapper_with_restart(php_socket_t fd, void *buf, size_t s return n; } -int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) { +static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) { #ifdef HAVE_FTP_SSL int err; bool retry = 0; @@ -1400,7 +1399,7 @@ static int my_poll(php_socket_t fd, int events, int timeout) { return n; } -int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) +static int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { zend_long size, sent; int n; @@ -1434,7 +1433,7 @@ int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) return len; } -int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) +static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { int n, nr_bytes; #ifdef HAVE_FTP_SSL @@ -1510,7 +1509,7 @@ int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) return (nr_bytes); } -int data_available(ftpbuf_t *ftp, php_socket_t s) +static int data_available(ftpbuf_t *ftp, php_socket_t s) { int n; @@ -1531,7 +1530,7 @@ int data_available(ftpbuf_t *ftp, php_socket_t s) return 1; } -int data_writeable(ftpbuf_t *ftp, php_socket_t s) +static int data_writeable(ftpbuf_t *ftp, php_socket_t s) { int n; @@ -1552,7 +1551,7 @@ int data_writeable(ftpbuf_t *ftp, php_socket_t s) return 1; } -int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) +static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) { int n; @@ -1573,7 +1572,7 @@ int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *a return accept(s, addr, addrlen); } -databuf_t* ftp_getdata(ftpbuf_t *ftp) +static databuf_t* ftp_getdata(ftpbuf_t *ftp) { int fd = -1; databuf_t *data; @@ -1703,7 +1702,7 @@ databuf_t* ftp_getdata(ftpbuf_t *ftp) return NULL; } -databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp) +static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp) { php_sockaddr_storage addr; socklen_t size; @@ -1874,7 +1873,7 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) { } #endif -void data_close(ftpbuf_t *ftp) +static void data_close(ftpbuf_t *ftp) { ZEND_ASSERT(ftp != NULL); databuf_t *data = ftp->data; @@ -1905,7 +1904,7 @@ void data_close(ftpbuf_t *ftp) efree(data); } -char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len) +static char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *path, const size_t path_len) { php_stream *tmpstream = NULL; databuf_t *data = NULL; From 169573bcb578d59b80e0457dae6d2f8f0fff56e9 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 19:43:17 +0100 Subject: [PATCH 270/503] ext/ftp: Use bool type instead of int type --- ext/ftp/ftp.c | 284 +++++++++++++++++++++++----------------------- ext/ftp/ftp.h | 32 +++--- ext/ftp/php_ftp.c | 26 ++--- 3 files changed, 169 insertions(+), 173 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index c707a784a1194..0b63822211f72 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -68,7 +68,7 @@ * it sends the string "cmd args\r\n" if args is non-null, or * "cmd\r\n" if args is null */ -static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len); +static bool ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len); /* wrapper around send/recv to handle timeouts */ static int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); @@ -76,13 +76,13 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen); /* reads a line the socket , returns true on success, false on error */ -static int ftp_readline(ftpbuf_t *ftp); +static bool ftp_readline(ftpbuf_t *ftp); /* reads an ftp response, returns true on success, false on error */ -static int ftp_getresp(ftpbuf_t *ftp); +static bool ftp_getresp(ftpbuf_t *ftp); /* sets the ftp transfer type */ -static int ftp_type(ftpbuf_t *ftp, ftptype_t type); +static bool ftp_type(ftpbuf_t *ftp, ftptype_t type); /* opens up a data stream */ static databuf_t* ftp_getdata(ftpbuf_t *ftp); @@ -194,17 +194,17 @@ void ftp_gc(ftpbuf_t *ftp) } } -int ftp_quit(ftpbuf_t *ftp) +bool ftp_quit(ftpbuf_t *ftp) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "QUIT", sizeof("QUIT")-1, NULL, (size_t) 0)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 221) { - return 0; + return false; } if (ftp->pwd) { @@ -212,7 +212,7 @@ int ftp_quit(ftpbuf_t *ftp) ftp->pwd = NULL; } - return 1; + return true; } #ifdef HAVE_FTP_SSL @@ -231,7 +231,7 @@ static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) } #endif -int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len) +bool ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len) { #ifdef HAVE_FTP_SSL SSL_CTX *ctx = NULL; @@ -240,28 +240,28 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char bool retry; #endif if (ftp == NULL) { - return 0; + return false; } #ifdef HAVE_FTP_SSL if (ftp->use_ssl && !ftp->ssl_active) { if (!ftp_putcmd(ftp, "AUTH", sizeof("AUTH")-1, "TLS", sizeof("TLS")-1)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } if (ftp->resp != 234) { if (!ftp_putcmd(ftp, "AUTH", sizeof("AUTH")-1, "SSL", sizeof("SSL")-1)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } if (ftp->resp != 334) { - return 0; + return false; } else { ftp->old_ssl = 1; ftp->use_ssl_for_data = 1; @@ -271,7 +271,7 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) { php_error_docref(NULL, E_WARNING, "Failed to create the SSL context"); - return 0; + return false; } ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; @@ -288,7 +288,7 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char if (ftp->ssl_handle == NULL) { php_error_docref(NULL, E_WARNING, "Failed to create the SSL handle"); - return 0; + return false; } SSL_set_fd(ftp->ssl_handle, ftp->fd); @@ -300,11 +300,11 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char /* TODO check if handling other error codes would make sense */ switch (err) { case SSL_ERROR_NONE: - retry = 0; + retry = false; break; case SSL_ERROR_ZERO_RETURN: - retry = 0; + retry = false; SSL_shutdown(ftp->ssl_handle); break; @@ -327,28 +327,28 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char php_error_docref(NULL, E_WARNING, "SSL/TLS handshake failed"); SSL_shutdown(ftp->ssl_handle); SSL_free(ftp->ssl_handle); - return 0; + return false; } } while (retry); - ftp->ssl_active = 1; + ftp->ssl_active = true; if (!ftp->old_ssl) { /* set protection buffersize to zero */ if (!ftp_putcmd(ftp, "PBSZ", sizeof("PBSZ")-1, "0", sizeof("0")-1)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } /* enable data conn encryption */ if (!ftp_putcmd(ftp, "PROT", sizeof("PROT")-1, "P", sizeof("P")-1)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299); @@ -357,30 +357,30 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char #endif if (!ftp_putcmd(ftp, "USER", sizeof("USER")-1, user, user_len)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } if (ftp->resp == 230) { - return 1; + return true; } if (ftp->resp != 331) { - return 0; + return false; } if (!ftp_putcmd(ftp, "PASS", sizeof("PASS")-1, pass, pass_len)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } return (ftp->resp == 230); } -int ftp_reinit(ftpbuf_t *ftp) +bool ftp_reinit(ftpbuf_t *ftp) { if (ftp == NULL) { - return 0; + return false; } ftp_gc(ftp); @@ -388,13 +388,13 @@ int ftp_reinit(ftpbuf_t *ftp) ftp->nb = 0; if (!ftp_putcmd(ftp, "REIN", sizeof("REIN")-1, NULL, (size_t) 0)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 220) { - return 0; + return false; } - return 1; + return true; } const char* ftp_syst(ftpbuf_t *ftp) @@ -459,19 +459,19 @@ const char* ftp_pwd(ftpbuf_t *ftp) return ftp->pwd; } -int ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) +bool ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "SITE EXEC", sizeof("SITE EXEC")-1, cmd, cmd_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 200) { - return 0; + return false; } - return 1; + return true; } void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value) @@ -491,10 +491,10 @@ void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_ } } -int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) +bool ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) { if (ftp == NULL) { - return 0; + return false; } if (ftp->pwd) { @@ -503,18 +503,18 @@ int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) } if (!ftp_putcmd(ftp, "CWD", sizeof("CWD")-1, dir, dir_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 250) { - return 0; + return false; } - return 1; + return true; } -int ftp_cdup(ftpbuf_t *ftp) +bool ftp_cdup(ftpbuf_t *ftp) { if (ftp == NULL) { - return 0; + return false; } if (ftp->pwd) { @@ -523,12 +523,12 @@ int ftp_cdup(ftpbuf_t *ftp) } if (!ftp_putcmd(ftp, "CDUP", sizeof("CDUP")-1, NULL, (size_t) 0)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 250) { - return 0; + return false; } - return 1; + return true; } zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) @@ -559,70 +559,70 @@ zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) return ret; } -int ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) +bool ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "RMD", sizeof("RMD")-1, dir, dir_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 250) { - return 0; + return false; } - return 1; + return true; } -int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) +bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) { char *buffer; size_t buffer_len; if (ftp == NULL || filename_len <= 0) { - return 0; + return false; } buffer_len = spprintf(&buffer, 0, "CHMOD %o %s", mode, filename); if (!buffer) { - return 0; + return false; } if (!ftp_putcmd(ftp, "SITE", sizeof("SITE")-1, buffer, buffer_len)) { efree(buffer); - return 0; + return false; } efree(buffer); if (!ftp_getresp(ftp) || ftp->resp != 200) { - return 0; + return false; } - return 1; + return true; } -int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) +bool ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) { char buffer[64]; int buffer_len; if (ftp == NULL || size <= 0) { - return 0; + return false; } buffer_len = snprintf(buffer, sizeof(buffer) - 1, ZEND_LONG_FMT, size); if (buffer_len < 0) { - return 0; + return false; } if (!ftp_putcmd(ftp, "ALLO", sizeof("ALLO")-1, buffer, buffer_len)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } if (response) { @@ -630,10 +630,10 @@ int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response) } if (ftp->resp < 200 || ftp->resp >= 300) { - return 0; + return false; } - return 1; + return true; } char** ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len) @@ -692,35 +692,35 @@ int ftp_mlsd_parse_line(HashTable *ht, const char *input) return SUCCESS; } -static int ftp_type(ftpbuf_t *ftp, ftptype_t type) +static bool ftp_type(ftpbuf_t *ftp, ftptype_t type) { const char *typechar; if (ftp == NULL) { - return 0; + return false; } if (type == ftp->type) { - return 1; + return true; } if (type == FTPTYPE_ASCII) { typechar = "A"; } else if (type == FTPTYPE_IMAGE) { typechar = "I"; } else { - return 0; + return false; } if (!ftp_putcmd(ftp, "TYPE", sizeof("TYPE")-1, typechar, 1)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 200) { - return 0; + return false; } ftp->type = type; - return 1; + return true; } -int ftp_pasv(ftpbuf_t *ftp, int pasv) +bool ftp_pasv(ftpbuf_t *ftp, int pasv) { char *ptr; union ipbox ipbox; @@ -730,21 +730,21 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv) struct sockaddr_in *sin; if (ftp == NULL) { - return 0; + return false; } if (pasv && ftp->pasv == 2) { - return 1; + return true; } ftp->pasv = 0; if (!pasv) { - return 1; + return true; } n = sizeof(ftp->pasvaddr); memset(&ftp->pasvaddr, 0, n); sa = (struct sockaddr *) &ftp->pasvaddr; if (getpeername(ftp->fd, sa, &n) < 0) { - return 0; + return false; } #ifdef HAVE_IPV6 @@ -754,16 +754,16 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv) /* try EPSV first */ if (!ftp_putcmd(ftp, "EPSV", sizeof("EPSV")-1, NULL, (size_t) 0)) { - return 0; + return false; } if (!ftp_getresp(ftp)) { - return 0; + return false; } if (ftp->resp == 229) { /* parse out the port */ for (ptr = ftp->inbuf; *ptr && *ptr != '('; ptr++); if (!*ptr) { - return 0; + return false; } delimiter = *++ptr; for (n = 0; *ptr && n < 3; ptr++) { @@ -774,10 +774,10 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv) sin6->sin6_port = htons((unsigned short) strtoul(ptr, &endptr, 10)); if (ptr == endptr || *endptr != delimiter) { - return 0; + return false; } ftp->pasv = 2; - return 1; + return true; } } @@ -785,16 +785,16 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv) #endif if (!ftp_putcmd(ftp, "PASV", sizeof("PASV")-1, NULL, (size_t) 0)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 227) { - return 0; + return false; } /* parse out the IP and port */ for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); n = sscanf(ptr, "%lu,%lu,%lu,%lu,%lu,%lu", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]); if (n != 6) { - return 0; + return false; } for (n = 0; n < 6; n++) { ipbox.c[n] = (unsigned char) b[n]; @@ -807,17 +807,17 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv) ftp->pasv = 2; - return 1; + return true; } -int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) +bool ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos) { databuf_t *data = NULL; size_t rcvd; char arg[MAX_LENGTH_OF_LONG]; if (ftp == NULL) { - return 0; + return false; } if (!ftp_type(ftp, type)) { goto bail; @@ -894,10 +894,10 @@ int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t goto bail; } - return 1; + return true; bail: data_close(ftp); - return 0; + return false; } static zend_result ftp_send_stream_to_data_socket(ftpbuf_t *ftp, databuf_t *data, php_stream *instream, ftptype_t type, bool send_once_and_return) @@ -973,13 +973,13 @@ static zend_result ftp_send_stream_to_data_socket(ftpbuf_t *ftp, databuf_t *data return SUCCESS; } -int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) +bool ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos) { databuf_t *data = NULL; char arg[MAX_LENGTH_OF_LONG]; if (ftp == NULL) { - return 0; + return false; } if (!ftp_type(ftp, type)) { goto bail; @@ -1021,18 +1021,18 @@ int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream * if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) { goto bail; } - return 1; + return true; bail: data_close(ftp); - return 0; + return false; } -int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type) +bool ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type) { databuf_t *data = NULL; if (ftp == NULL) { - return 0; + return false; } if (!ftp_type(ftp, type)) { goto bail; @@ -1061,10 +1061,10 @@ int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_strea if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) { goto bail; } - return 1; + return true; bail: data_close(ftp); - return 0; + return false; } zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len) @@ -1128,69 +1128,69 @@ time_t ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len) return stamp; } -int ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len) +bool ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "DELE", sizeof("DELE")-1, path, path_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 250) { - return 0; + return false; } - return 1; + return true; } -int ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len) +bool ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "RNFR", sizeof("RNFR")-1, src, src_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 350) { - return 0; + return false; } if (!ftp_putcmd(ftp, "RNTO", sizeof("RNTO")-1, dest, dest_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp != 250) { - return 0; + return false; } - return 1; + return true; } -int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) +bool ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) { if (ftp == NULL) { - return 0; + return false; } if (!ftp_putcmd(ftp, "SITE", sizeof("SITE")-1, cmd, cmd_len)) { - return 0; + return false; } if (!ftp_getresp(ftp) || ftp->resp < 200 || ftp->resp >= 300) { - return 0; + return false; } - return 1; + return true; } -static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) +static bool ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) { int size; char *data; if (strpbrk(cmd, "\r\n")) { - return 0; + return false; } /* build the output buffer */ if (args && args[0]) { /* "cmd args\r\n\0" */ if (cmd_len + args_len + 4 > FTP_BUFSIZE) { - return 0; + return false; } if (strpbrk(args, "\r\n")) { return 0; @@ -1199,7 +1199,7 @@ static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, cons } else { /* "cmd\r\n\0" */ if (cmd_len + 3 > FTP_BUFSIZE) { - return 0; + return false; } size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s\r\n", cmd); } @@ -1211,12 +1211,12 @@ static int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, cons ftp->extra = NULL; if (my_send(ftp, ftp->fd, data, size) != size) { - return 0; + return false; } - return 1; + return true; } -static int ftp_readline(ftpbuf_t *ftp) +static bool ftp_readline(ftpbuf_t *ftp) { long size, rcvd; char *data, *eol; @@ -1244,39 +1244,39 @@ static int ftp_readline(ftpbuf_t *ftp) if ((ftp->extralen = --rcvd) == 0) { ftp->extra = NULL; } - return 1; + return true; } else if (*eol == '\n') { *eol = 0; ftp->extra = eol + 1; if ((ftp->extralen = --rcvd) == 0) { ftp->extra = NULL; } - return 1; + return true; } } data = eol; if ((rcvd = my_recv(ftp, ftp->fd, data, size)) < 1) { *data = 0; - return 0; + return false; } } while (size); *data = 0; - return 0; + return false; } -static int ftp_getresp(ftpbuf_t *ftp) +static bool ftp_getresp(ftpbuf_t *ftp) { if (ftp == NULL) { - return 0; + return false; } ftp->resp = 0; while (1) { if (!ftp_readline(ftp)) { - return 0; + return false; } /* Break out when the end-tag is found */ @@ -1287,7 +1287,7 @@ static int ftp_getresp(ftpbuf_t *ftp) /* translate the tag */ if (!isdigit(ftp->inbuf[0]) || !isdigit(ftp->inbuf[1]) || !isdigit(ftp->inbuf[2])) { - return 0; + return false; } ftp->resp = 100 * (ftp->inbuf[0] - '0') + 10 * (ftp->inbuf[1] - '0') + (ftp->inbuf[2] - '0'); @@ -1297,7 +1297,7 @@ static int ftp_getresp(ftpbuf_t *ftp) if (ftp->extra) { ftp->extra -= 4; } - return 1; + return true; } static ssize_t my_send_wrapper_with_restart(php_socket_t fd, const void *buf, size_t size, int flags) { @@ -1509,7 +1509,7 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) return (nr_bytes); } -static int data_available(ftpbuf_t *ftp, php_socket_t s) +static bool data_available(ftpbuf_t *ftp, php_socket_t s) { int n; @@ -1524,13 +1524,13 @@ static int data_available(ftpbuf_t *ftp, php_socket_t s) #endif } php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror(errno, buf, sizeof buf)); - return 0; + return false; } - return 1; + return true; } -static int data_writeable(ftpbuf_t *ftp, php_socket_t s) +static bool data_writeable(ftpbuf_t *ftp, php_socket_t s) { int n; @@ -1545,10 +1545,10 @@ static int data_writeable(ftpbuf_t *ftp, php_socket_t s) #endif } php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror(errno, buf, sizeof buf)); - return 0; + return false; } - return 1; + return true; } static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index bcd69059cbc86..8f25a5089beb1 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -97,7 +97,7 @@ ftpbuf_t* ftp_open(const char *host, short port, zend_long timeout_sec); /* quits from the ftp session (it still needs to be closed) * return true on success, false on error */ -int ftp_quit(ftpbuf_t *ftp); +bool ftp_quit(ftpbuf_t *ftp); /* frees up any cached data held in the ftp buffer */ void ftp_gc(ftpbuf_t *ftp); @@ -106,10 +106,10 @@ void ftp_gc(ftpbuf_t *ftp); void ftp_close(ftpbuf_t *ftp); /* logs into the FTP server, returns true on success, false on error */ -int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len); +bool ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len); /* reinitializes the connection, returns true on success, false on error */ -int ftp_reinit(ftpbuf_t *ftp); +bool ftp_reinit(ftpbuf_t *ftp); /* returns the remote system type (NULL on error) */ const char* ftp_syst(ftpbuf_t *ftp); @@ -118,16 +118,16 @@ const char* ftp_syst(ftpbuf_t *ftp); const char* ftp_pwd(ftpbuf_t *ftp); /* exec a command [special features], return true on success, false on error */ -int ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); +bool ftp_exec(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); /* send a raw ftp command, return response as a hashtable, NULL on error */ void ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value); /* changes directories, return true on success, false on error */ -int ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); +bool ftp_chdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* changes to parent directory, return true on success, false on error */ -int ftp_cdup(ftpbuf_t *ftp); +bool ftp_cdup(ftpbuf_t *ftp); /* creates a directory, return the directory name on success, NULL on error. * the return value must be freed @@ -135,17 +135,17 @@ int ftp_cdup(ftpbuf_t *ftp); zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* removes a directory, return true on success, false on error */ -int ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); +bool ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* Set permissions on a file */ -int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); +bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); /* Allocate space on remote server with ALLO command * Many servers will respond with 202 Allocation not necessary, * however some servers will not accept STOR or APPE until ALLO is confirmed. * If response is passed, it is estrdup()ed from ftp->inbuf and must be freed * or assigned to a zval returned to the user */ -int ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response); +bool ftp_alloc(ftpbuf_t *ftp, const zend_long size, zend_string **response); /* returns a NULL-terminated array of filenames in the given path * or NULL on error. the return array must be freed (but don't @@ -175,22 +175,22 @@ char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len); /* switches passive mode on or off * returns true on success, false on error */ -int ftp_pasv(ftpbuf_t *ftp, int pasv); +bool ftp_pasv(ftpbuf_t *ftp, int pasv); /* retrieves a file and saves its contents to outfp * returns true on success, false on error */ -int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); +bool ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos); /* stores the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ -int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); +bool ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos); /* append the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ -int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type); +bool ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type); /* returns the size of the given file, or -1 on error */ zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len); @@ -199,13 +199,13 @@ zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len); time_t ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len); /* renames a file on the server */ -int ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len); +bool ftp_rename(ftpbuf_t *ftp, const char *src, const size_t src_len, const char *dest, const size_t dest_len); /* deletes the file from the server */ -int ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len); +bool ftp_delete(ftpbuf_t *ftp, const char *path, const size_t path_len); /* sends a SITE command to the server */ -int ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); +bool ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len); /* retrieves part of a file and saves its contents to outfp * returns true on success, false on error diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 17dc94b728eba..a1e0ff1f809ce 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -162,7 +162,7 @@ PHP_FUNCTION(ftp_connect) ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS; #ifdef HAVE_FTP_SSL /* disable ssl */ - ftp->use_ssl = 0; + ftp->use_ssl = false; #endif object_init_ex(return_value, php_ftp_ce); @@ -198,7 +198,7 @@ PHP_FUNCTION(ftp_ssl_connect) ftp->autoseek = FTP_DEFAULT_AUTOSEEK; ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS; /* enable ssl */ - ftp->use_ssl = 1; + ftp->use_ssl = true; object_init_ex(return_value, php_ftp_ce); ftp_object_from_zend_object(Z_OBJ_P(return_value))->ftp = ftp; @@ -432,7 +432,7 @@ PHP_FUNCTION(ftp_alloc) { zval *z_ftp, *zresponse = NULL; ftpbuf_t *ftp; - zend_long size, ret; + zend_long size; zend_string *response = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|z", &z_ftp, php_ftp_ce, &size, &zresponse) == FAILURE) { @@ -440,17 +440,13 @@ PHP_FUNCTION(ftp_alloc) } GET_FTPBUF(ftp, z_ftp); - ret = ftp_alloc(ftp, size, zresponse ? &response : NULL); + bool ret = ftp_alloc(ftp, size, zresponse ? &response : NULL); if (response) { ZEND_TRY_ASSIGN_REF_STR(zresponse, response); } - if (!ret) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(ret); } /* }}} */ @@ -797,8 +793,8 @@ PHP_FUNCTION(ftp_nb_get) } /* configuration */ - ftp->direction = 0; /* recv */ - ftp->closestream = 1; /* do close */ + ftp->direction = false; /* recv */ + ftp->closestream = true; /* do close */ if ((ret = ftp_nb_get(ftp, outstream, remote, remote_len, xtype, resumepos)) == PHP_FTP_FAILED) { php_stream_close(outstream); @@ -950,8 +946,8 @@ PHP_FUNCTION(ftp_nb_fput) } /* configuration */ - ftp->direction = 1; /* send */ - ftp->closestream = 0; /* do not close */ + ftp->direction = true; /* send */ + ftp->closestream = false; /* do not close */ if (((ret = ftp_nb_put(ftp, remote, remote_len, stream, xtype, startpos)) == PHP_FTP_FAILED)) { if (*ftp->inbuf) { @@ -1091,8 +1087,8 @@ PHP_FUNCTION(ftp_nb_put) } /* configuration */ - ftp->direction = 1; /* send */ - ftp->closestream = 1; /* do close */ + ftp->direction = true; /* send */ + ftp->closestream = true; /* do close */ ret = ftp_nb_put(ftp, remote, remote_len, instream, xtype, startpos); From 7fcdf1cfa20258609e2e68b10e373f822b8111df Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 19:56:22 +0100 Subject: [PATCH 271/503] ext/ftp: Use zend_result type instead of int type --- ext/ftp/ftp.c | 2 +- ext/ftp/ftp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 0b63822211f72..ffe955766bc0d 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -651,7 +651,7 @@ char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len) return ftp_genlist(ftp, "MLSD", sizeof("MLSD")-1, path, path_len); } -int ftp_mlsd_parse_line(HashTable *ht, const char *input) +zend_result ftp_mlsd_parse_line(HashTable *ht, const char *input) { zval zstr; const char *end = input + strlen(input); diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 8f25a5089beb1..0e73ee30850f4 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -163,7 +163,7 @@ char** ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recu /* populates a hashtable with the facts contained in one line of * an MLSD response. */ -int ftp_mlsd_parse_line(HashTable *ht, const char *input); +zend_result ftp_mlsd_parse_line(HashTable *ht, const char *input); /* returns a NULL-terminated array of lines returned by the ftp * MLSD command for the given path or NULL on error. the return From 96cf1b5a9f39fc020bdaab7a894641d0412004bb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 20:17:13 +0100 Subject: [PATCH 272/503] ext/ftp: Use size_t type instead of int type --- ext/ftp/ftp.c | 4 ++-- ext/ftp/ftp.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index ffe955766bc0d..39555d8c7e322 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -573,12 +573,12 @@ bool ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len) return true; } -bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) +bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const size_t filename_len) { char *buffer; size_t buffer_len; - if (ftp == NULL || filename_len <= 0) { + if (ftp == NULL || filename_len == 0) { return false; } diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 0e73ee30850f4..5f01f202b8e26 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -138,7 +138,7 @@ zend_string* ftp_mkdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); bool ftp_rmdir(ftpbuf_t *ftp, const char *dir, const size_t dir_len); /* Set permissions on a file */ -bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); +bool ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const size_t filename_len); /* Allocate space on remote server with ALLO command * Many servers will respond with 202 Allocation not necessary, From c8559648faa8f507c7528634a16f60e11cc85ddf Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 20:15:38 +0100 Subject: [PATCH 273/503] [skip ci] ext/ftp: Fix typos --- ext/ftp/php_ftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index a1e0ff1f809ce..fb771a66d73e4 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -390,7 +390,7 @@ PHP_FUNCTION(ftp_rmdir) } GET_FTPBUF(ftp, z_ftp); - /* remove directorie */ + /* remove directories */ if (!ftp_rmdir(ftp, dir, dir_len)) { if (*ftp->inbuf) { php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf); From 1dd788acdcf4a58aa6ea7fb573bbe16d38b4bb36 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 20:24:33 +0100 Subject: [PATCH 274/503] ext/ftp: Change return type of ftp_set_option() to true It either returns true or throws an Error --- ext/ftp/ftp.stub.php | 2 +- ext/ftp/ftp_arginfo.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/ftp/ftp.stub.php b/ext/ftp/ftp.stub.php index beab97f2d98e4..6560dd8930186 100644 --- a/ext/ftp/ftp.stub.php +++ b/ext/ftp/ftp.stub.php @@ -132,7 +132,7 @@ function ftp_close(FTP\Connection $ftp): bool {} function ftp_quit(FTP\Connection $ftp): bool {} /** @param int|bool $value */ - function ftp_set_option(FTP\Connection $ftp, int $option, $value): bool {} + function ftp_set_option(FTP\Connection $ftp, int $option, $value): true {} function ftp_get_option(FTP\Connection $ftp, int $option): int|bool {} } diff --git a/ext/ftp/ftp_arginfo.h b/ext/ftp/ftp_arginfo.h index e28a549f9d670..77bc47df03f69 100644 --- a/ext/ftp/ftp_arginfo.h +++ b/ext/ftp/ftp_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 072486274a3361dee3655cfd046a293cfb8a2757 */ + * Stub hash: 29606d7114a0698b8ae231173a624b17c196ffec */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_ftp_connect, 0, 1, FTP\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) @@ -182,7 +182,7 @@ ZEND_END_ARG_INFO() #define arginfo_ftp_quit arginfo_ftp_cdup -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_set_option, 0, 3, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_set_option, 0, 3, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, ftp, FTP\\Connection, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) ZEND_ARG_INFO(0, value) From 8033b058a97a59aa467f6031d313110f26c714b5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Apr 2025 20:35:04 +0100 Subject: [PATCH 275/503] ext/ftp: Remove output field of ftpbuf_t struct It was only used once, and removing it reduces the size of a userland FTP object by 4096 bytes --- ext/ftp/ftp.c | 8 +++----- ext/ftp/ftp.h | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 39555d8c7e322..f37ee68617616 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -1181,7 +1181,7 @@ bool ftp_site(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len) static bool ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, const char *args, const size_t args_len) { int size; - char *data; + char data[FTP_BUFSIZE]; if (strpbrk(cmd, "\r\n")) { return false; @@ -1195,17 +1195,15 @@ static bool ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, con if (strpbrk(args, "\r\n")) { return 0; } - size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s %s\r\n", cmd, args); + size = slprintf(data, sizeof(data), "%s %s\r\n", cmd, args); } else { /* "cmd\r\n\0" */ if (cmd_len + 3 > FTP_BUFSIZE) { return false; } - size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s\r\n", cmd); + size = slprintf(data, sizeof(data), "%s\r\n", cmd); } - data = ftp->outbuf; - /* Clear the inbuf and extra-lines buffer */ ftp->inbuf[0] = '\0'; ftp->extra = NULL; diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 5f01f202b8e26..241f92f57ec35 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -60,7 +60,6 @@ typedef struct ftpbuf char inbuf[FTP_BUFSIZE]; /* last response text */ char *extra; /* extra characters */ int extralen; /* number of extra chars */ - char outbuf[FTP_BUFSIZE]; /* command output buffer */ char *pwd; /* cached pwd */ char *syst; /* cached system type */ ftptype_t type; /* current transfer type */ From 2c326d8222199e952d3a9ab07621724bbf8d93c6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 16 Mar 2025 00:42:45 +0000 Subject: [PATCH 276/503] ext/standard: Add Directory test with messed up internal state --- ...adonly_handle_by_pass_via_ArrayObject.phpt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt diff --git a/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt new file mode 100644 index 0000000000000..cc57fc6933aa4 --- /dev/null +++ b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt @@ -0,0 +1,34 @@ +--TEST-- +Changing Directory::$handle property +--FILE-- +getMessage(), PHP_EOL; +} +var_dump($d->handle); + +try { + $s = $d->read(); + var_dump($s); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + unset($ao['handle']); + var_dump($d->handle); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +resource(3) of type (stream) +TypeError: Directory::read(): Argument #1 must be a valid Directory resource +Error: Typed property Directory::$handle must not be accessed before initialization From 4101a8c09997a7ca1a681a193eb005f399088bfd Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 16 Mar 2025 01:58:48 +0000 Subject: [PATCH 277/503] ext/standard/dir.c: Refactor implementation of Directory and dir functions --- ext/standard/dir.c | 224 ++++++++++++------ ext/standard/dir.stub.php | 9 - ext/standard/dir_arginfo.h | 14 +- .../dir/closedir_variation2-win32-mb.phpt | 2 +- .../tests/dir/closedir_variation2.phpt | 2 +- .../tests/dir/dir_basic-win32-mb.phpt | 2 +- ext/standard/tests/dir/dir_basic.phpt | 2 +- .../dir/rewinddir_variation2-win32-mb.phpt | 2 +- .../tests/dir/rewinddir_variation2.phpt | 2 +- ...adonly_handle_by_pass_via_ArrayObject.phpt | 2 +- ...flection_create_instance_no_construct.phpt | 2 +- 11 files changed, 160 insertions(+), 103 deletions(-) diff --git a/ext/standard/dir.c b/ext/standard/dir.c index a2a50eab7f51d..845fcd03eeadc 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -59,39 +59,6 @@ static zend_function *dir_class_get_constructor(zend_object *object) return NULL; } -#define FETCH_DIRP() \ - myself = getThis(); \ - if (!myself) { \ - ZEND_PARSE_PARAMETERS_START(0, 1) \ - Z_PARAM_OPTIONAL \ - Z_PARAM_RESOURCE_OR_NULL(id) \ - ZEND_PARSE_PARAMETERS_END(); \ - if (id) { \ - if ((dirp = (php_stream *)zend_fetch_resource(Z_RES_P(id), "Directory", php_file_le_stream())) == NULL) { \ - RETURN_THROWS(); \ - } \ - } else { \ - if (!DIRG(default_dir)) { \ - zend_type_error("No resource supplied"); \ - RETURN_THROWS(); \ - } \ - if ((dirp = (php_stream *)zend_fetch_resource(DIRG(default_dir), "Directory", php_file_le_stream())) == NULL) { \ - RETURN_THROWS(); \ - } \ - } \ - } else { \ - ZEND_PARSE_PARAMETERS_NONE(); \ - zval *handle_zv = Z_DIRECTORY_HANDLE_P(myself); \ - if (Z_TYPE_P(handle_zv) != IS_RESOURCE) { \ - zend_throw_error(NULL, "Unable to find my handle property"); \ - RETURN_THROWS(); \ - } \ - if ((dirp = (php_stream *)zend_fetch_resource_ex(handle_zv, "Directory", php_file_le_stream())) == NULL) { \ - RETURN_THROWS(); \ - } \ - } - - static void php_set_default_dir(zend_resource *res) { if (DIRG(default_dir)) { @@ -189,29 +156,166 @@ PHP_FUNCTION(dir) } /* }}} */ + +static php_stream* php_dir_get_directory_stream_from_user_arg(zval *arg) +{ + zend_resource *res; + if (arg == NULL) { + if (UNEXPECTED(DIRG(default_dir) == NULL)) { + zend_type_error("No resource supplied"); + return NULL; + } + res = DIRG(default_dir); + } else { + ZEND_ASSERT(Z_TYPE_P(arg) == IS_RESOURCE); + res = Z_RES_P(arg); + } + + if (UNEXPECTED(res->type != php_file_le_stream())) { + zend_argument_type_error(1, "must be a valid Directory resource"); + return NULL; + } + php_stream *dir_stream = (php_stream*) res->ptr; + if (UNEXPECTED((dir_stream->flags & PHP_STREAM_FLAG_IS_DIR)) == 0) { + zend_argument_type_error(1, "must be a valid Directory resource"); + return NULL; + } + return dir_stream; +} + +static php_stream* php_dir_get_directory_stream_from_this(zval *this_z) +{ + zval *handle_zv = Z_DIRECTORY_HANDLE_P(this_z); + if (UNEXPECTED(Z_TYPE_P(handle_zv) != IS_RESOURCE)) { + zend_throw_error(NULL, "Internal directory stream has been altered"); + return NULL; + } + zend_resource *res = Z_RES_P(handle_zv); + /* Assume the close() method was called + * (instead of the hacky case where a different resource would have been set via the ArrayObject "hack") */ + if (UNEXPECTED(res->type != php_file_le_stream())) { + /* TypeError is used for BC, TODO: Use base Error in PHP 9 */ + zend_type_error("Directory::%s(): cannot use Directory resource after it has been closed", get_active_function_name()); + return NULL; + } + php_stream *dir_stream = (php_stream*) res->ptr; + if (UNEXPECTED((dir_stream->flags & PHP_STREAM_FLAG_IS_DIR)) == 0) { + zend_throw_error(NULL, "Internal directory stream has been altered"); + return NULL; + } + return dir_stream; +} + /* {{{ Close directory connection identified by the dir_handle */ PHP_FUNCTION(closedir) { - zval *id = NULL, *myself; - php_stream *dirp; - zend_resource *res; + zval *id = NULL; - FETCH_DIRP(); + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_RESOURCE_OR_NULL(id) + ZEND_PARSE_PARAMETERS_END(); - if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) { - zend_argument_type_error(1, "must be a valid Directory resource"); + php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + if (UNEXPECTED(dirp == NULL)) { RETURN_THROWS(); } + zend_resource *res = dirp->res; + zend_list_close(res); - res = dirp->res; - zend_list_close(dirp->res); + if (res == DIRG(default_dir)) { + php_set_default_dir(NULL); + } +} +/* }}} */ + +PHP_METHOD(Directory, close) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_stream *dirp = php_dir_get_directory_stream_from_this(ZEND_THIS); + if (UNEXPECTED(dirp == NULL)) { + RETURN_THROWS(); + } + + zend_resource *res = dirp->res; + zend_list_close(res); if (res == DIRG(default_dir)) { php_set_default_dir(NULL); } } + +/* {{{ Rewind dir_handle back to the start */ +PHP_FUNCTION(rewinddir) +{ + zval *id = NULL; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_RESOURCE_OR_NULL(id) + ZEND_PARSE_PARAMETERS_END(); + + php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + if (UNEXPECTED(dirp == NULL)) { + RETURN_THROWS(); + } + + php_stream_rewinddir(dirp); +} /* }}} */ +PHP_METHOD(Directory, rewind) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_stream *dirp = php_dir_get_directory_stream_from_this(ZEND_THIS); + if (UNEXPECTED(dirp == NULL)) { + RETURN_THROWS(); + } + + php_stream_rewinddir(dirp); +} + +/* {{{ Read directory entry from dir_handle */ +PHP_FUNCTION(readdir) +{ + zval *id = NULL; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_RESOURCE_OR_NULL(id) + ZEND_PARSE_PARAMETERS_END(); + + php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + if (UNEXPECTED(dirp == NULL)) { + RETURN_THROWS(); + } + + php_stream_dirent entry; + if (php_stream_readdir(dirp, &entry)) { + RETURN_STRING(entry.d_name); + } + RETURN_FALSE; +} +/* }}} */ + +PHP_METHOD(Directory, read) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_stream *dirp = php_dir_get_directory_stream_from_this(ZEND_THIS); + if (UNEXPECTED(dirp == NULL)) { + RETURN_THROWS(); + } + + php_stream_dirent entry; + if (php_stream_readdir(dirp, &entry)) { + RETURN_STRING(entry.d_name); + } + RETURN_FALSE; +} + #if defined(HAVE_CHROOT) && !defined(ZTS) && defined(ENABLE_CHROOT_FUNC) /* {{{ Change root directory */ PHP_FUNCTION(chroot) @@ -300,44 +404,6 @@ PHP_FUNCTION(getcwd) } /* }}} */ -/* {{{ Rewind dir_handle back to the start */ -PHP_FUNCTION(rewinddir) -{ - zval *id = NULL, *myself; - php_stream *dirp; - - FETCH_DIRP(); - - if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) { - zend_argument_type_error(1, "must be a valid Directory resource"); - RETURN_THROWS(); - } - - php_stream_rewinddir(dirp); -} -/* }}} */ - -/* {{{ Read directory entry from dir_handle */ -PHP_FUNCTION(readdir) -{ - zval *id = NULL, *myself; - php_stream *dirp; - php_stream_dirent entry; - - FETCH_DIRP(); - - if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) { - zend_argument_type_error(1, "must be a valid Directory resource"); - RETURN_THROWS(); - } - - if (php_stream_readdir(dirp, &entry)) { - RETURN_STRINGL(entry.d_name, strlen(entry.d_name)); - } - RETURN_FALSE; -} -/* }}} */ - #ifdef HAVE_GLOB /* {{{ Find pathnames matching a pattern */ PHP_FUNCTION(glob) diff --git a/ext/standard/dir.stub.php b/ext/standard/dir.stub.php index 457a965352516..afca1fcacc421 100644 --- a/ext/standard/dir.stub.php +++ b/ext/standard/dir.stub.php @@ -98,18 +98,9 @@ final class Directory /** @var resource */ public readonly mixed $handle; - /** - * @implementation-alias closedir - */ public function close(): void {} - /** - * @implementation-alias rewinddir - */ public function rewind(): void {} - /** - * @implementation-alias readdir - */ public function read(): string|false {} } diff --git a/ext/standard/dir_arginfo.h b/ext/standard/dir_arginfo.h index 9b293f3cd753f..f73b0e5d86ad1 100644 --- a/ext/standard/dir_arginfo.h +++ b/ext/standard/dir_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 069117bab1b9502faf516307aa7e80308f7b7f13 */ + * Stub hash: 543d0d12062ed88dab7a3ac4354499682c5c7166 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Directory_close, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -9,14 +9,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Directory_read, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_END_ARG_INFO() -ZEND_FUNCTION(closedir); -ZEND_FUNCTION(rewinddir); -ZEND_FUNCTION(readdir); +ZEND_METHOD(Directory, close); +ZEND_METHOD(Directory, rewind); +ZEND_METHOD(Directory, read); static const zend_function_entry class_Directory_methods[] = { - ZEND_RAW_FENTRY("close", zif_closedir, arginfo_class_Directory_close, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("rewind", zif_rewinddir, arginfo_class_Directory_rewind, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("read", zif_readdir, arginfo_class_Directory_read, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(Directory, close, arginfo_class_Directory_close, ZEND_ACC_PUBLIC) + ZEND_ME(Directory, rewind, arginfo_class_Directory_rewind, ZEND_ACC_PUBLIC) + ZEND_ME(Directory, read, arginfo_class_Directory_read, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt b/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt index 9999cb8b10e51..08842ae7f7b10 100644 --- a/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt +++ b/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt @@ -47,5 +47,5 @@ NULL Directory Handle: resource(%d) of type (Unknown) -- Close directory handle second time: -- -closedir(): %s is not a valid Directory resource +closedir(): Argument #1 ($dir_handle) must be a valid Directory resource Directory Handle: resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/closedir_variation2.phpt b/ext/standard/tests/dir/closedir_variation2.phpt index e4b782c255ce8..e8518c3d3efcf 100644 --- a/ext/standard/tests/dir/closedir_variation2.phpt +++ b/ext/standard/tests/dir/closedir_variation2.phpt @@ -41,5 +41,5 @@ NULL Directory Handle: resource(%d) of type (Unknown) -- Close directory handle second time: -- -closedir(): supplied resource is not a valid Directory resource +closedir(): Argument #1 ($dir_handle) must be a valid Directory resource Directory Handle: resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/dir_basic-win32-mb.phpt b/ext/standard/tests/dir/dir_basic-win32-mb.phpt index 74e2cda6f070b..040596d40d6e7 100644 --- a/ext/standard/tests/dir/dir_basic-win32-mb.phpt +++ b/ext/standard/tests/dir/dir_basic-win32-mb.phpt @@ -85,5 +85,5 @@ object(Directory)#%d (2) { } Test read after closing the dir: -Directory::read(): %s is not a valid Directory resource +Directory::read(): cannot use Directory resource after it has been closed Done diff --git a/ext/standard/tests/dir/dir_basic.phpt b/ext/standard/tests/dir/dir_basic.phpt index d474122ba243b..17a2b42bcdaea 100644 --- a/ext/standard/tests/dir/dir_basic.phpt +++ b/ext/standard/tests/dir/dir_basic.phpt @@ -79,5 +79,5 @@ object(Directory)#%d (2) { } Test read after closing the dir: -Directory::read(): supplied resource is not a valid Directory resource +Directory::read(): cannot use Directory resource after it has been closed Done diff --git a/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt b/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt index ab639c7f24f3c..7cb9f2616c5c9 100644 --- a/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt +++ b/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt @@ -42,4 +42,4 @@ resource(%d) of type (stream) string(%d) "%s" -- Call to rewinddir() -- -rewinddir(): %s is not a valid Directory resource +rewinddir(): Argument #1 ($dir_handle) must be a valid Directory resource diff --git a/ext/standard/tests/dir/rewinddir_variation2.phpt b/ext/standard/tests/dir/rewinddir_variation2.phpt index 654c68cecbe01..16d66da7f8287 100644 --- a/ext/standard/tests/dir/rewinddir_variation2.phpt +++ b/ext/standard/tests/dir/rewinddir_variation2.phpt @@ -36,4 +36,4 @@ resource(%d) of type (stream) string(%d) "%s" -- Call to rewinddir() -- -rewinddir(): supplied resource is not a valid Directory resource +rewinddir(): Argument #1 ($dir_handle) must be a valid Directory resource diff --git a/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt index cc57fc6933aa4..91416f2c71202 100644 --- a/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt +++ b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt @@ -30,5 +30,5 @@ try { ?> --EXPECT-- resource(3) of type (stream) -TypeError: Directory::read(): Argument #1 must be a valid Directory resource +Error: Internal directory stream has been altered Error: Typed property Directory::$handle must not be accessed before initialization diff --git a/ext/standard/tests/directory/DirectoryClass_reflection_create_instance_no_construct.phpt b/ext/standard/tests/directory/DirectoryClass_reflection_create_instance_no_construct.phpt index 35b07591635fd..95999581f31c9 100644 --- a/ext/standard/tests/directory/DirectoryClass_reflection_create_instance_no_construct.phpt +++ b/ext/standard/tests/directory/DirectoryClass_reflection_create_instance_no_construct.phpt @@ -27,4 +27,4 @@ object(Directory)#2 (0) { ["handle"]=> uninitialized(mixed) } -Error: Unable to find my handle property +Error: Internal directory stream has been altered From 68665d3cb5dcda5b966fc9edd577581be763ee63 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 17 Mar 2025 14:23:41 +0000 Subject: [PATCH 278/503] ext/standard/dir.c: Use new PHP_Z_PARAM_STREAM_OR_NULL() ZPP specifier --- ext/standard/dir.c | 35 ++++++++----------- .../dir/closedir_variation2-win32-mb.phpt | 2 +- .../tests/dir/closedir_variation2.phpt | 2 +- .../dir/rewinddir_variation2-win32-mb.phpt | 2 +- .../tests/dir/rewinddir_variation2.phpt | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/ext/standard/dir.c b/ext/standard/dir.c index 845fcd03eeadc..b468681ac364a 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -157,25 +157,18 @@ PHP_FUNCTION(dir) /* }}} */ -static php_stream* php_dir_get_directory_stream_from_user_arg(zval *arg) +static php_stream* php_dir_get_directory_stream_from_user_arg(php_stream *dir_stream) { - zend_resource *res; - if (arg == NULL) { + if (dir_stream == NULL) { if (UNEXPECTED(DIRG(default_dir) == NULL)) { zend_type_error("No resource supplied"); return NULL; } - res = DIRG(default_dir); - } else { - ZEND_ASSERT(Z_TYPE_P(arg) == IS_RESOURCE); - res = Z_RES_P(arg); + zend_resource *res = DIRG(default_dir); + ZEND_ASSERT(res->type == php_file_le_stream()); + dir_stream = (php_stream*) res->ptr; } - if (UNEXPECTED(res->type != php_file_le_stream())) { - zend_argument_type_error(1, "must be a valid Directory resource"); - return NULL; - } - php_stream *dir_stream = (php_stream*) res->ptr; if (UNEXPECTED((dir_stream->flags & PHP_STREAM_FLAG_IS_DIR)) == 0) { zend_argument_type_error(1, "must be a valid Directory resource"); return NULL; @@ -209,14 +202,14 @@ static php_stream* php_dir_get_directory_stream_from_this(zval *this_z) /* {{{ Close directory connection identified by the dir_handle */ PHP_FUNCTION(closedir) { - zval *id = NULL; + php_stream *dirp = NULL; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_RESOURCE_OR_NULL(id) + PHP_Z_PARAM_STREAM_OR_NULL(dirp) ZEND_PARSE_PARAMETERS_END(); - php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + dirp = php_dir_get_directory_stream_from_user_arg(dirp); if (UNEXPECTED(dirp == NULL)) { RETURN_THROWS(); } @@ -249,14 +242,14 @@ PHP_METHOD(Directory, close) /* {{{ Rewind dir_handle back to the start */ PHP_FUNCTION(rewinddir) { - zval *id = NULL; + php_stream *dirp = NULL; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_RESOURCE_OR_NULL(id) + PHP_Z_PARAM_STREAM_OR_NULL(dirp) ZEND_PARSE_PARAMETERS_END(); - php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + dirp = php_dir_get_directory_stream_from_user_arg(dirp); if (UNEXPECTED(dirp == NULL)) { RETURN_THROWS(); } @@ -280,14 +273,14 @@ PHP_METHOD(Directory, rewind) /* {{{ Read directory entry from dir_handle */ PHP_FUNCTION(readdir) { - zval *id = NULL; + php_stream *dirp = NULL; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_RESOURCE_OR_NULL(id) + PHP_Z_PARAM_STREAM_OR_NULL(dirp) ZEND_PARSE_PARAMETERS_END(); - php_stream *dirp = php_dir_get_directory_stream_from_user_arg(id); + dirp = php_dir_get_directory_stream_from_user_arg(dirp); if (UNEXPECTED(dirp == NULL)) { RETURN_THROWS(); } diff --git a/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt b/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt index 08842ae7f7b10..1ada5b7fb36c5 100644 --- a/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt +++ b/ext/standard/tests/dir/closedir_variation2-win32-mb.phpt @@ -47,5 +47,5 @@ NULL Directory Handle: resource(%d) of type (Unknown) -- Close directory handle second time: -- -closedir(): Argument #1 ($dir_handle) must be a valid Directory resource +closedir(): Argument #1 ($dir_handle) must be an open stream resource Directory Handle: resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/closedir_variation2.phpt b/ext/standard/tests/dir/closedir_variation2.phpt index e8518c3d3efcf..7898c9ae0ff13 100644 --- a/ext/standard/tests/dir/closedir_variation2.phpt +++ b/ext/standard/tests/dir/closedir_variation2.phpt @@ -41,5 +41,5 @@ NULL Directory Handle: resource(%d) of type (Unknown) -- Close directory handle second time: -- -closedir(): Argument #1 ($dir_handle) must be a valid Directory resource +closedir(): Argument #1 ($dir_handle) must be an open stream resource Directory Handle: resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt b/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt index 7cb9f2616c5c9..4bd69b61ff7d6 100644 --- a/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt +++ b/ext/standard/tests/dir/rewinddir_variation2-win32-mb.phpt @@ -42,4 +42,4 @@ resource(%d) of type (stream) string(%d) "%s" -- Call to rewinddir() -- -rewinddir(): Argument #1 ($dir_handle) must be a valid Directory resource +rewinddir(): Argument #1 ($dir_handle) must be an open stream resource diff --git a/ext/standard/tests/dir/rewinddir_variation2.phpt b/ext/standard/tests/dir/rewinddir_variation2.phpt index 16d66da7f8287..7ce3c522352d7 100644 --- a/ext/standard/tests/dir/rewinddir_variation2.phpt +++ b/ext/standard/tests/dir/rewinddir_variation2.phpt @@ -36,4 +36,4 @@ resource(%d) of type (stream) string(%d) "%s" -- Call to rewinddir() -- -rewinddir(): Argument #1 ($dir_handle) must be a valid Directory resource +rewinddir(): Argument #1 ($dir_handle) must be an open stream resource From bda9ff8338c6394e23b9b60d0f104c2553e2f5a7 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 15:12:06 +0100 Subject: [PATCH 279/503] ext/gd: Flip size and nb arguments for safe_emalloc() The size should be the second one --- ext/gd/gd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 5822c368e3de2..688658b2899b0 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -649,7 +649,7 @@ PHP_FUNCTION(imagesetstyle) } /* copy the style values in the stylearr */ - stylearr = safe_emalloc(sizeof(int), num_styles, 0); + stylearr = safe_emalloc(num_styles, sizeof(int), 0); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(styles), item) { stylearr[index++] = zval_get_long(item); From d80682e753af13a89ad71ee78100ce44045f175d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:02:47 +0200 Subject: [PATCH 280/503] Avoid allocation in zend_enum_get_case_cstr() (#18239) Future uses of this internal API are planned, and we can easily avoid an allocation by factoring out the common code. --- Zend/zend_enum.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index ccafca48fe9b8..6baa34cc50125 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -610,8 +610,7 @@ ZEND_API void zend_enum_add_case_cstr(zend_class_entry *ce, const char *name, zv zend_string_release(name_str); } -ZEND_API zend_object *zend_enum_get_case(zend_class_entry *ce, zend_string *name) { - zend_class_constant *c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), name); +static zend_object *zend_enum_case_from_class_constant(zend_class_constant *c) { ZEND_ASSERT(c && "Must be a valid enum case"); ZEND_ASSERT(ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE); @@ -624,9 +623,12 @@ ZEND_API zend_object *zend_enum_get_case(zend_class_entry *ce, zend_string *name return Z_OBJ(c->value); } +ZEND_API zend_object *zend_enum_get_case(zend_class_entry *ce, zend_string *name) { + zend_class_constant *c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), name); + return zend_enum_case_from_class_constant(c); +} + ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char *name) { - zend_string *name_str = zend_string_init(name, strlen(name), 0); - zend_object *result = zend_enum_get_case(ce, name_str); - zend_string_release(name_str); - return result; + zend_class_constant *c = zend_hash_str_find_ptr(CE_CONSTANTS_TABLE(ce), name, strlen(name)); + return zend_enum_case_from_class_constant(c); } From 1304719aae71c693fb4ff3cc8ade9cf449880313 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 5 Apr 2025 04:27:52 +0100 Subject: [PATCH 281/503] Zend/zend_inheritance: Prevent variable shadowing --- Zend/zend_inheritance.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 8747e11d151fc..2a308a2c1581c 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -2978,9 +2978,9 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent zend_function **hooks = new_prop->hooks = zend_arena_alloc(&CG(arena), ZEND_PROPERTY_HOOK_STRUCT_SIZE); memcpy(hooks, property_info->hooks, ZEND_PROPERTY_HOOK_STRUCT_SIZE); - for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { - if (hooks[i]) { - zend_function *old_fn = hooks[i]; + for (uint32_t j = 0; j < ZEND_PROPERTY_HOOK_COUNT; j++) { + if (hooks[j]) { + zend_function *old_fn = hooks[j]; /* Hooks are not yet supported for internal properties. */ ZEND_ASSERT(ZEND_USER_CODE(old_fn->type)); @@ -2995,7 +2995,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent zend_fixup_trait_method(new_fn, ce); - hooks[i] = new_fn; + hooks[j] = new_fn; } } ce->ce_flags |= ZEND_ACC_USE_GUARDS; @@ -3343,10 +3343,8 @@ static zend_op_array *zend_lazy_method_load( static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) { - zend_class_entry *ce; - Bucket *p, *end; + zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); - ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); memcpy(ce, pce, sizeof(zend_class_entry)); ce->ce_flags &= ~ZEND_ACC_IMMUTABLE; ce->refcount = 1; @@ -3372,11 +3370,11 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) /* methods */ ce->function_table.pDestructor = ZEND_FUNCTION_DTOR; if (!(HT_FLAGS(&ce->function_table) & HASH_FLAG_UNINITIALIZED)) { - p = emalloc(HT_SIZE(&ce->function_table)); + Bucket *p = emalloc(HT_SIZE(&ce->function_table)); memcpy(p, HT_GET_DATA_ADDR(&ce->function_table), HT_USED_SIZE(&ce->function_table)); HT_SET_DATA_ADDR(&ce->function_table, p); p = ce->function_table.arData; - end = p + ce->function_table.nNumUsed; + const Bucket *end = p + ce->function_table.nNumUsed; for (; p != end; p++) { zend_op_array *op_array = Z_PTR(p->val); zend_op_array *new_op_array = Z_PTR(p->val) = zend_lazy_method_load(op_array, ce, pce); @@ -3412,11 +3410,11 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) /* properties_info */ if (!(HT_FLAGS(&ce->properties_info) & HASH_FLAG_UNINITIALIZED)) { - p = emalloc(HT_SIZE(&ce->properties_info)); + Bucket *p = emalloc(HT_SIZE(&ce->properties_info)); memcpy(p, HT_GET_DATA_ADDR(&ce->properties_info), HT_USED_SIZE(&ce->properties_info)); HT_SET_DATA_ADDR(&ce->properties_info, p); p = ce->properties_info.arData; - end = p + ce->properties_info.nNumUsed; + const Bucket *end = p + ce->properties_info.nNumUsed; for (; p != end; p++) { zend_property_info *prop_info, *new_prop_info; @@ -3448,11 +3446,11 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) /* constants table */ if (!(HT_FLAGS(&ce->constants_table) & HASH_FLAG_UNINITIALIZED)) { - p = emalloc(HT_SIZE(&ce->constants_table)); + Bucket *p = emalloc(HT_SIZE(&ce->constants_table)); memcpy(p, HT_GET_DATA_ADDR(&ce->constants_table), HT_USED_SIZE(&ce->constants_table)); HT_SET_DATA_ADDR(&ce->constants_table, p); p = ce->constants_table.arData; - end = p + ce->constants_table.nNumUsed; + const Bucket *end = p + ce->constants_table.nNumUsed; for (; p != end; p++) { zend_class_constant *c, *new_c; From 10c9e4decfedf185dd98041e4bd50b426fe6b6c8 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 5 Apr 2025 04:35:04 +0100 Subject: [PATCH 282/503] Zend/zend_inheritance: Reduce scope of variables Fix some types at the same time --- Zend/zend_inheritance.c | 65 ++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 2a308a2c1581c..2219f584db31e 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -706,7 +706,6 @@ ZEND_API inheritance_status zend_perform_covariant_type_check( } } - zend_type *single_type; inheritance_status early_exit_status; bool have_unresolved = false; @@ -728,6 +727,7 @@ ZEND_API inheritance_status zend_perform_covariant_type_check( * We need to iterate over fe_type (U_i) first and the logic is independent of * whether proto_type is a union or intersection (only the inner check differs). */ early_exit_status = INHERITANCE_ERROR; + zend_type *single_type; ZEND_TYPE_FOREACH(fe_type, single_type) { inheritance_status status; /* Union has an intersection type as it's member */ @@ -790,7 +790,7 @@ static inheritance_status zend_do_perform_implementation_check( const zend_function *fe, zend_class_entry *fe_scope, const zend_function *proto, zend_class_entry *proto_scope) /* {{{ */ { - uint32_t i, num_args, proto_num_args, fe_num_args; + uint32_t num_args, proto_num_args, fe_num_args; inheritance_status status, local_status; bool proto_is_variadic, fe_is_variadic; @@ -831,7 +831,7 @@ static inheritance_status zend_do_perform_implementation_check( num_args = MAX(proto_num_args, fe_num_args); status = INHERITANCE_SUCCESS; - for (i = 0; i < num_args; i++) { + for (uint32_t i = 0; i < num_args; i++) { zend_arg_info *proto_arg_info = i < proto_num_args ? &proto->common.arg_info[i] : proto_is_variadic ? &proto->common.arg_info[proto_num_args - 1] : NULL; @@ -933,7 +933,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( smart_str_appendc(&str, '('); if (fptr->common.arg_info) { - uint32_t i, num_args, required; + uint32_t num_args, required; zend_arg_info *arg_info = fptr->common.arg_info; required = fptr->common.required_num_args; @@ -941,7 +941,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) { num_args++; } - for (i = 0; i < num_args;) { + for (uint32_t i = 0; i < num_args;) { zend_append_type_hint(&str, scope, arg_info, 0); if (ZEND_ARG_SEND_MODE(arg_info)) { @@ -1451,10 +1451,9 @@ static prop_variance prop_get_variance(const zend_property_info *prop_info) { static void do_inherit_property(zend_property_info *parent_info, zend_string *key, zend_class_entry *ce) /* {{{ */ { zval *child = zend_hash_find_known_hash(&ce->properties_info, key); - zend_property_info *child_info; if (UNEXPECTED(child)) { - child_info = Z_PTR_P(child); + zend_property_info *child_info = Z_PTR_P(child); if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_CHANGED)) { child_info->flags |= ZEND_ACC_CHANGED; } @@ -1596,7 +1595,6 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_en { /* expects interface to be contained in ce's interface list already */ uint32_t i, ce_num, if_num = iface->num_interfaces; - zend_class_entry *entry; ce_num = ce->num_interfaces; @@ -1608,7 +1606,7 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_en /* Inherit the interfaces, only if they're not already inherited by the class */ while (if_num--) { - entry = iface->interfaces[if_num]; + zend_class_entry *entry = iface->interfaces[if_num]; for (i = 0; i < ce_num; i++) { if (ce->interfaces[i] == entry) { break; @@ -1830,7 +1828,6 @@ static void zend_link_hooked_object_iter(zend_class_entry *ce) { ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *parent_ce, bool checked) /* {{{ */ { zend_property_info *property_info; - zend_function *func; zend_string *key; if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) { @@ -2021,6 +2018,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par if (!checked) { flags |= ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY; } + zend_function *func; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { do_inherit_method(key, func, ce, 0, flags); } ZEND_HASH_FOREACH_END(); @@ -2196,15 +2194,13 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { - uint32_t i, ignore = 0; + uint32_t ignore = 0; uint32_t current_iface_num = ce->num_interfaces; uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0; - zend_string *key; - zend_class_constant *c; ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED); - for (i = 0; i < ce->num_interfaces; i++) { + for (uint32_t i = 0; i < ce->num_interfaces; i++) { if (ce->interfaces[i] == NULL) { memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i)); i--; @@ -2217,6 +2213,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } } if (ignore) { + zend_string *key; + zend_class_constant *c; /* Check for attempt to redeclare interface constants */ ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { do_inherit_constant_check(ce, c, key); @@ -2238,15 +2236,14 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry **interfaces) /* {{{ */ { - zend_class_entry *iface; uint32_t num_parent_interfaces = ce->parent ? ce->parent->num_interfaces : 0; uint32_t num_interfaces = num_parent_interfaces; zend_string *key; zend_class_constant *c; - uint32_t i, j; + uint32_t i; for (i = 0; i < ce->num_interfaces; i++) { - iface = interfaces[num_parent_interfaces + i]; + zend_class_entry *iface = interfaces[num_parent_interfaces + i]; if (!(iface->ce_flags & ZEND_ACC_LINKED)) { add_dependency_obligation(ce, iface); } @@ -2255,7 +2252,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name)); return; } - for (j = 0; j < num_interfaces; j++) { + for (uint32_t j = 0; j < num_interfaces; j++) { if (interfaces[j] == iface) { if (j >= num_parent_interfaces) { efree(interfaces); @@ -2442,7 +2439,6 @@ static void zend_traits_check_private_final_inheritance(uint32_t original_fn_fla static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable *exclude_table, zend_class_entry **aliases) /* {{{ */ { zend_trait_alias *alias, **alias_ptr; - zend_string *lcname; zend_function fn_copy; int i; @@ -2466,7 +2462,7 @@ static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, z zend_traits_check_private_final_inheritance(fn->common.fn_flags, &fn_copy, alias->alias); - lcname = zend_string_tolower(alias->alias); + zend_string *lcname = zend_string_tolower(alias->alias); zend_add_trait_method(ce, alias->alias, lcname, &fn_copy); zend_string_release_ex(lcname, 0); } @@ -2512,14 +2508,12 @@ static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, z static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait, zend_class_entry **traits) /* {{{ */ { - uint32_t i; - if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) { zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", ZSTR_VAL(trait->name)); return 0; } - for (i = 0; i < ce->num_traits; i++) { + for (uint32_t i = 0; i < ce->num_traits; i++) { if (traits[i] == trait) { return i; } @@ -2532,7 +2526,6 @@ static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *t static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_entry **traits, HashTable ***exclude_tables_ptr, zend_class_entry ***aliases_ptr) /* {{{ */ { size_t i, j = 0; - zend_trait_precedence **precedences; zend_trait_precedence *cur_precedence; zend_trait_method_reference *cur_method_ref; zend_string *lc_trait_name; @@ -2545,7 +2538,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e if (ce->trait_precedences) { exclude_tables = ecalloc(ce->num_traits, sizeof(HashTable*)); i = 0; - precedences = ce->trait_precedences; + zend_trait_precedence **precedences = ce->trait_precedences; ce->trait_precedences = NULL; while ((cur_precedence = precedences[i])) { /** Resolve classes for all precedence operations. */ @@ -2736,10 +2729,8 @@ static const zend_class_entry* find_first_constant_definition(const zend_class_e * process like this is needed to find the location of the first definition * of the constant from traits. */ - size_t i; - if (colliding_ce == ce) { - for (i = 0; i < current_trait; i++) { + for (size_t i = 0; i < current_trait; i++) { if (traits[i] && zend_hash_exists(&traits[i]->constants_table, constant_name)) { return traits[i]; @@ -2806,9 +2797,7 @@ static bool do_trait_constant_check( static void zend_do_traits_constant_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */ { - size_t i; - - for (i = 0; i < ce->num_traits; i++) { + for (uint32_t i = 0; i < ce->num_traits; i++) { zend_string *constant_name; zend_class_constant *constant; @@ -2850,10 +2839,8 @@ static void zend_do_traits_constant_binding(zend_class_entry *ce, zend_class_ent static const zend_class_entry* find_first_property_definition(const zend_class_entry *ce, zend_class_entry **traits, size_t current_trait, zend_string *prop_name, const zend_class_entry *colliding_ce) /* {{{ */ { - size_t i; - if (colliding_ce == ce) { - for (i = 0; i < current_trait; i++) { + for (size_t i = 0; i < current_trait; i++) { if (traits[i] && zend_hash_exists(&traits[i]->properties_info, prop_name)) { return traits[i]; @@ -2867,20 +2854,17 @@ static const zend_class_entry* find_first_property_definition(const zend_class_e static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */ { - size_t i; zend_property_info *property_info; const zend_property_info *colliding_prop; - zend_property_info *new_prop; zend_string* prop_name; zval* prop_value; - zend_string *doc_comment; /* In the following steps the properties are inserted into the property table * for that, a very strict approach is applied: * - check for compatibility, if not compatible with any property in class -> fatal * - if compatible, then strict notice */ - for (i = 0; i < ce->num_traits; i++) { + for (uint32_t i = 0; i < ce->num_traits; i++) { if (!traits[i]) { continue; } @@ -2960,12 +2944,13 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent prop_value = &tmp_prop_value; ZVAL_UNDEF(&tmp_prop_value); } - doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL; + + zend_string *doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL; zend_type type = property_info->type; /* Assumption: only userland classes can use traits, as such the type must be arena allocated */ zend_type_copy_ctor(&type, /* use arena */ true, /* persistent */ false); - new_prop = zend_declare_typed_property(ce, prop_name, prop_value, flags, doc_comment, type); + zend_property_info *new_prop = zend_declare_typed_property(ce, prop_name, prop_value, flags, doc_comment, type); if (property_info->attributes) { new_prop->attributes = property_info->attributes; From dcf664963f2b822ae8c6dc3a23016dfad6d94ac7 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 5 Apr 2025 04:25:49 +0100 Subject: [PATCH 283/503] Zend/zend_inheritance: Add some const modifiers --- Zend/zend_inheritance.c | 62 ++++++++++++++++++++--------------------- Zend/zend_inheritance.h | 6 ++-- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 2219f584db31e..eaa8bf3a7009b 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -96,7 +96,7 @@ static void zend_type_copy_ctor(zend_type *const type, bool use_arena, bool pers } } -static zend_function *zend_duplicate_internal_function(zend_function *func, const zend_class_entry *ce) /* {{{ */ +static zend_function *zend_duplicate_internal_function(const zend_function *func, const zend_class_entry *ce) /* {{{ */ { zend_function *new_function; @@ -310,7 +310,7 @@ static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name } /* Instanceof that's safe to use on unlinked classes. */ -static bool unlinked_instanceof(zend_class_entry *ce1, const zend_class_entry *ce2) { +static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) { if (ce1 == ce2) { return 1; } @@ -347,7 +347,7 @@ static bool unlinked_instanceof(zend_class_entry *ce1, const zend_class_entry *c } } else { for (i = 0; i < ce1->num_interfaces; i++) { - zend_class_entry *ce = zend_lookup_class_ex( + const zend_class_entry *ce = zend_lookup_class_ex( ce1->interface_names[i].name, ce1->interface_names[i].lc_name, ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD); /* Avoid recursing if class implements itself. */ @@ -362,7 +362,7 @@ static bool unlinked_instanceof(zend_class_entry *ce1, const zend_class_entry *c } static bool zend_type_permits_self( - zend_type type, zend_class_entry *scope, zend_class_entry *self) { + zend_type type, const zend_class_entry *scope, zend_class_entry *self) { if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) { return 1; } @@ -374,7 +374,7 @@ static bool zend_type_permits_self( ZEND_TYPE_FOREACH(type, single_type) { if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type)); - zend_class_entry *ce = lookup_class(self, name); + const zend_class_entry *ce = lookup_class(self, name); if (ce && unlinked_instanceof(self, ce)) { return 1; } @@ -584,7 +584,7 @@ static inheritance_status zend_is_class_subtype_of_type( return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } -static zend_string *get_class_from_type(zend_class_entry *scope, zend_type single_type) { +static zend_string *get_class_from_type(const zend_class_entry *scope, zend_type single_type) { if (ZEND_TYPE_HAS_NAME(single_type)) { return resolve_class_name(scope, ZEND_TYPE_NAME(single_type)); } @@ -973,7 +973,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( { uint32_t idx = i; zend_op *op = fptr->op_array.opcodes; - zend_op *end = op + fptr->op_array.last; + const zend_op *end = op + fptr->op_array.last; ++idx; while (op < end) { @@ -1366,7 +1366,7 @@ static inheritance_status verify_property_type_compatibility( return INHERITANCE_SUCCESS; } -static bool property_has_operation(zend_property_info *prop_info, zend_property_hook_kind kind) +static bool property_has_operation(const zend_property_info *prop_info, zend_property_hook_kind kind) { return (!(prop_info->flags & ZEND_ACC_VIRTUAL) && (kind == ZEND_PROPERTY_HOOK_GET || !(prop_info->flags & ZEND_ACC_READONLY))) @@ -1649,7 +1649,7 @@ static inheritance_status class_constant_types_compatible(const zend_class_const } static bool do_inherit_constant_check( - zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name); + zend_class_entry *ce, const zend_class_constant *parent_constant, zend_string *name); static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */ { @@ -1722,7 +1722,7 @@ void zend_build_properties_info_table(zend_class_entry *ce) } ZEND_HASH_FOREACH_END(); } -ZEND_API void zend_verify_hooked_property(zend_class_entry *ce, zend_property_info *prop_info, zend_string *prop_name) +ZEND_API void zend_verify_hooked_property(const zend_class_entry *ce, zend_property_info *prop_info, zend_string *prop_name) { if (!prop_info->hooks) { return; @@ -1746,7 +1746,7 @@ ZEND_API void zend_verify_hooked_property(zend_class_entry *ce, zend_property_in ZVAL_NULL(&ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)]); } for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { - zend_function *func = prop_info->hooks[i]; + const zend_function *func = prop_info->hooks[i]; if (func) { if ((zend_property_hook_kind)i == ZEND_PROPERTY_HOOK_GET && (func->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -2077,7 +2077,7 @@ static zend_always_inline bool check_trait_property_or_constant_value_compatibil /** @return bool Returns true if the class constant should be inherited, i.e. whether it doesn't already exist. */ static bool do_inherit_constant_check( - zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name + zend_class_entry *ce, const zend_class_constant *parent_constant, zend_string *name ) { zval *zv = zend_hash_find_known_hash(&ce->constants_table, name); if (zv == NULL) { @@ -2124,7 +2124,7 @@ static bool do_inherit_constant_check( } /* }}} */ -static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ +static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, const zend_class_entry *iface) /* {{{ */ { if (do_inherit_constant_check(ce, c, name)) { zend_class_constant *ct; @@ -2301,7 +2301,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry /* }}} */ -void zend_inheritance_check_override(zend_class_entry *ce) +void zend_inheritance_check_override(const zend_class_entry *ce) { zend_function *f; @@ -2423,7 +2423,7 @@ static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce) /* } /* }}} */ -static void zend_traits_check_private_final_inheritance(uint32_t original_fn_flags, zend_function *fn_copy, zend_string *name) +static void zend_traits_check_private_final_inheritance(uint32_t original_fn_flags, const zend_function *fn_copy, const zend_string *name) { /* If the function was originally already private+final, then it will have * already been warned about. Only emit this error when the used trait method @@ -2506,7 +2506,7 @@ static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, z } /* }}} */ -static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait, zend_class_entry **traits) /* {{{ */ +static uint32_t zend_check_trait_usage(const zend_class_entry *ce, const zend_class_entry *trait, zend_class_entry **traits) /* {{{ */ { if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) { zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", ZSTR_VAL(trait->name)); @@ -2612,7 +2612,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e aliases = ecalloc(i, sizeof(zend_class_entry*)); i = 0; while (ce->trait_aliases[i]) { - zend_trait_alias *cur_alias = ce->trait_aliases[i]; + const zend_trait_alias *cur_alias = ce->trait_aliases[i]; cur_method_ref = &ce->trait_aliases[i]->trait_method; lcname = zend_string_tolower(cur_method_ref->method_name); if (cur_method_ref->class_name) { @@ -3206,7 +3206,7 @@ static void add_property_hook_obligation( static void resolve_delayed_variance_obligations(zend_class_entry *ce); -static void check_variance_obligation(variance_obligation *obligation) { +static void check_variance_obligation(const variance_obligation *obligation) { if (obligation->type == OBLIGATION_DEPENDENCY) { zend_class_entry *dependency_ce = obligation->dependency_ce; if (dependency_ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) { @@ -3245,7 +3245,7 @@ static void check_variance_obligation(variance_obligation *obligation) { } } -static void load_delayed_classes(zend_class_entry *ce) { +static void load_delayed_classes(const zend_class_entry *ce) { HashTable *delayed_autoloads = CG(delayed_autoloads); if (!delayed_autoloads) { return; @@ -3274,11 +3274,11 @@ static void load_delayed_classes(zend_class_entry *ce) { } static void resolve_delayed_variance_obligations(zend_class_entry *ce) { - HashTable *all_obligations = CG(delayed_variance_obligations), *obligations; + HashTable *all_obligations = CG(delayed_variance_obligations); zend_ulong num_key = (zend_ulong) (uintptr_t) ce; ZEND_ASSERT(all_obligations != NULL); - obligations = zend_hash_index_find_ptr(all_obligations, num_key); + const HashTable *obligations = zend_hash_index_find_ptr(all_obligations, num_key); ZEND_ASSERT(obligations != NULL); variance_obligation *obligation; @@ -3312,7 +3312,7 @@ static void check_unrecoverable_load_failure(const zend_class_entry *ce) { } while (0) static zend_op_array *zend_lazy_method_load( - zend_op_array *op_array, zend_class_entry *ce, const zend_class_entry *pce) { + const zend_op_array *op_array, zend_class_entry *ce, const zend_class_entry *pce) { ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION); ZEND_ASSERT(op_array->scope == pce); ZEND_ASSERT(op_array->prototype == NULL); @@ -3326,7 +3326,7 @@ static zend_op_array *zend_lazy_method_load( return new_op_array; } -static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) +static zend_class_entry *zend_lazy_class_load(const zend_class_entry *pce) { zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); @@ -3344,7 +3344,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) if (ce->default_properties_table) { zval *dst = emalloc(sizeof(zval) * ce->default_properties_count); zval *src = ce->default_properties_table; - zval *end = src + ce->default_properties_count; + const zval *end = src + ce->default_properties_count; ce->default_properties_table = dst; for (; src != end; src++, dst++) { @@ -3384,7 +3384,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) if (ce->default_static_members_table) { zval *dst = emalloc(sizeof(zval) * ce->default_static_members_count); zval *src = ce->default_static_members_table; - zval *end = src + ce->default_static_members_count; + const zval *end = src + ce->default_static_members_count; ce->default_static_members_table = dst; for (; src != end; src++, dst++) { @@ -3401,9 +3401,9 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) p = ce->properties_info.arData; const Bucket *end = p + ce->properties_info.nNumUsed; for (; p != end; p++) { - zend_property_info *prop_info, *new_prop_info; + zend_property_info *new_prop_info; - prop_info = Z_PTR(p->val); + const zend_property_info *prop_info = Z_PTR(p->val); ZEND_ASSERT(prop_info->ce == pce); ZEND_ASSERT(prop_info->prototype == prop_info); new_prop_info= zend_arena_alloc(&CG(arena), sizeof(zend_property_info)); @@ -3437,9 +3437,9 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) p = ce->constants_table.arData; const Bucket *end = p + ce->constants_table.nNumUsed; for (; p != end; p++) { - zend_class_constant *c, *new_c; + zend_class_constant *new_c; - c = Z_PTR(p->val); + const zend_class_constant *c = Z_PTR(p->val); ZEND_ASSERT(c->ce == pce); new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); Z_PTR(p->val) = new_c; @@ -3464,7 +3464,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce) } while (0) #endif -ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, zend_string *key) /* {{{ */ +ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, const zend_string *key) /* {{{ */ { /* Load parent/interface dependencies first, so we can still gracefully abort linking * with an exception and remove the class from the class table. This is only possible @@ -3767,7 +3767,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string /* }}} */ /* Check whether early binding is prevented due to unresolved types in inheritance checks. */ -static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */ +static inheritance_status zend_can_early_bind(zend_class_entry *ce, const zend_class_entry *parent_ce) /* {{{ */ { zend_string *key; zend_function *parent_func; diff --git a/Zend/zend_inheritance.h b/Zend/zend_inheritance.h index 477874181e416..7171a9385f3ba 100644 --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@ -32,13 +32,13 @@ static zend_always_inline void zend_do_inheritance(zend_class_entry *ce, zend_cl zend_do_inheritance_ex(ce, parent_ce, 0); } -ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, zend_string *key); +ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, const zend_string *key); void zend_verify_abstract_class(zend_class_entry *ce); void zend_build_properties_info_table(zend_class_entry *ce); ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding); -void zend_inheritance_check_override(zend_class_entry *ce); +void zend_inheritance_check_override(const zend_class_entry *ce); ZEND_API extern zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces); ZEND_API extern zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies); @@ -53,7 +53,7 @@ typedef enum { ZEND_API zend_inheritance_status zend_verify_property_hook_variance(const zend_property_info *prop_info, const zend_function *func); ZEND_API ZEND_COLD ZEND_NORETURN void zend_hooked_property_variance_error(const zend_property_info *prop_info); ZEND_API ZEND_COLD ZEND_NORETURN void zend_hooked_property_variance_error_ex(zend_string *value_param_name, zend_string *class_name, zend_string *prop_name); -ZEND_API void zend_verify_hooked_property(zend_class_entry *ce, zend_property_info *prop_info, zend_string *prop_name); +ZEND_API void zend_verify_hooked_property(const zend_class_entry *ce, zend_property_info *prop_info, zend_string *prop_name); END_EXTERN_C() From 462b170a30c3521b8c40f798630c005a29e89b88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 5 Apr 2025 04:41:19 +0100 Subject: [PATCH 284/503] Zend/zend_inheritance: Use bool instead of uint32_t --- Zend/zend_inheritance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index eaa8bf3a7009b..53cd8533fd3e1 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -2194,7 +2194,7 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { - uint32_t ignore = 0; + bool ignore = false; uint32_t current_iface_num = ce->num_interfaces; uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0; @@ -2206,7 +2206,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry i--; } else if (ce->interfaces[i] == iface) { if (EXPECTED(i < parent_iface_num)) { - ignore = 1; + ignore = true; } else { zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name)); } From fe8dffef5df949a3bf574023c2ee442fcc0adb3e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 4 Apr 2025 06:55:59 +0100 Subject: [PATCH 285/503] Fixed GH-18243: imagettftext underflow/overflow on size argument. close GH-18245 --- NEWS | 2 ++ ext/gd/gd.c | 11 ++++++++++ ext/gd/tests/gh18243.phpt | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 ext/gd/tests/gh18243.phpt diff --git a/NEWS b/NEWS index 92b199270cf4d..774058d253783 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - GD: . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage in gdImageCrop(). (David Carlier) + . Fixed GH-18243 imagettftext() overflow/underflow on font size value. + (David Carlier) - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. diff --git a/ext/gd/gd.c b/ext/gd/gd.c index ae03b602cdc5b..6b727a211189a 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3082,6 +3082,17 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode) im = php_gd_libgdimageptr_from_zval_p(IM); } + // FT_F26Dot6 is a signed long alias + if (ptsize < (double)LONG_MIN / 64 || ptsize > (double)LONG_MAX / 64) { + zend_argument_value_error(2, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (zend_long)((double)LONG_MIN / 64), (zend_long)((double)LONG_MAX / 64)); + RETURN_THROWS(); + } + + if (UNEXPECTED(!zend_finite(ptsize))) { + zend_argument_value_error(2, "must be finite"); + RETURN_THROWS(); + } + /* convert angle to radians */ angle = angle * (M_PI/180); diff --git a/ext/gd/tests/gh18243.phpt b/ext/gd/tests/gh18243.phpt new file mode 100644 index 0000000000000..3235098a3dcc2 --- /dev/null +++ b/ext/gd/tests/gh18243.phpt @@ -0,0 +1,42 @@ +--TEST-- +GH-18243: imagefttext underflow/overflow on $size +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + imagettftext($im, PHP_INT_MIN, 0, 15, 60, 0, $font, ""); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + imagettftext($im, NAN, 0, 15, 60, 0, $font, ""); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + imagettftext($im, INF, 0, 15, 60, 0, $font, ""); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +imagettftext(): Argument #2 ($size) must be between %i and %d +imagettftext(): Argument #2 ($size) must be between %i and %d +imagettftext(): Argument #2 ($size) must be finite +imagettftext(): Argument #2 ($size) must be between %i and %d From 404059f018f8f276e2f69880530251b163b8315e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 5 Apr 2025 17:04:14 +0200 Subject: [PATCH 286/503] [ci skip] UPGRADING: Performance updates --- UPGRADING | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/UPGRADING b/UPGRADING index 082439b9264c8..26ed02c9af9a0 100644 --- a/UPGRADING +++ b/UPGRADING @@ -436,6 +436,13 @@ PHP 8.5 UPGRADE NOTES . Improved performance of the following methods: getValue(), getRawValue(), isInitialized(), setValue(), setRawValue(). +- SPL: + . Improved performance of dimension accessors and methods of SplFixedArray. + +- Standard: + . Improved performance of array functions with callbacks + (array_find, array_filter, array_map, usort, ...). + - XMLReader: . Improved property access performance. From b535a54f5f55b94b6d3440959ff8c445fc211188 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:12:45 +0100 Subject: [PATCH 287/503] ext/gd: Mark return types as true instead of bool --- ext/gd/gd.stub.php | 68 ++++++++++++++++++++++----------------------- ext/gd/gd_arginfo.h | 50 +++++++++++++++++---------------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index 347e43e728b87..b3b82766ee981 100644 --- a/ext/gd/gd.stub.php +++ b/ext/gd/gd.stub.php @@ -496,19 +496,19 @@ function imagetruecolortopalette(GdImage $image, bool $dither, int $num_colors): function imagepalettetotruecolor(GdImage $image): bool {} -function imagecolormatch(GdImage $image1, GdImage $image2): bool {} +function imagecolormatch(GdImage $image1, GdImage $image2): true {} -function imagesetthickness(GdImage $image, int $thickness): bool {} +function imagesetthickness(GdImage $image, int $thickness): true {} -function imagefilledellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): bool {} +function imagefilledellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): true {} -function imagefilledarc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color, int $style): bool {} +function imagefilledarc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color, int $style): true {} -function imagealphablending(GdImage $image, bool $enable): bool {} +function imagealphablending(GdImage $image, bool $enable): true {} -function imagesavealpha(GdImage $image, bool $enable): bool {} +function imagesavealpha(GdImage $image, bool $enable): true {} -function imagelayereffect(GdImage $image, int $effect): bool {} +function imagelayereffect(GdImage $image, int $effect): true {} function imagecolorallocatealpha(GdImage $image, int $red, int $green, int $blue, int $alpha): int|false {} @@ -518,7 +518,7 @@ function imagecolorclosestalpha(GdImage $image, int $red, int $green, int $blue, function imagecolorexactalpha(GdImage $image, int $red, int $green, int $blue, int $alpha): int {} -function imagecopyresampled(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): bool {} +function imagecopyresampled(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): true {} #ifdef PHP_WIN32 @@ -533,9 +533,9 @@ function imagegrabscreen(): GdImage|false {} /** @refcount 1 */ function imagerotate(GdImage $image, float $angle, int $background_color): GdImage|false {} -function imagesettile(GdImage $image, GdImage $tile): bool {} +function imagesettile(GdImage $image, GdImage $tile): true {} -function imagesetbrush(GdImage $image, GdImage $brush): bool {} +function imagesetbrush(GdImage $image, GdImage $brush): true {} /** @refcount 1 */ function imagecreate(int $width, int $height): GdImage|false {} @@ -635,7 +635,7 @@ function imagegd2(GdImage $image, ?string $file = null, int $chunk_size = 128, i function imagebmp(GdImage $image, $file = null, bool $compressed = true): bool {} #endif -function imagedestroy(GdImage $image): bool {} +function imagedestroy(GdImage $image): true {} function imagecolorallocate(GdImage $image, int $red, int $green, int $blue): int|false {} @@ -647,7 +647,7 @@ function imagecolorclosest(GdImage $image, int $red, int $green, int $blue): int function imagecolorclosesthwb(GdImage $image, int $red, int $green, int $blue): int {} -function imagecolordeallocate(GdImage $image, int $color): bool {} +function imagecolordeallocate(GdImage $image, int $color): true {} function imagecolorresolve(GdImage $image, int $red, int $green, int $blue): int {} @@ -661,25 +661,25 @@ function imagecolorset(GdImage $image, int $color, int $red, int $green, int $bl */ function imagecolorsforindex(GdImage $image, int $color): array {} -function imagegammacorrect(GdImage $image, float $input_gamma, float $output_gamma): bool {} +function imagegammacorrect(GdImage $image, float $input_gamma, float $output_gamma): true {} -function imagesetpixel(GdImage $image, int $x, int $y, int $color): bool {} +function imagesetpixel(GdImage $image, int $x, int $y, int $color): true {} -function imageline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} +function imageline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): true {} -function imagedashedline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} +function imagedashedline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): true {} -function imagerectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} +function imagerectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): true {} -function imagefilledrectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} +function imagefilledrectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): true {} -function imagearc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color): bool {} +function imagearc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color): true {} -function imageellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): bool {} +function imageellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): true {} -function imagefilltoborder(GdImage $image, int $x, int $y, int $border_color, int $color): bool {} +function imagefilltoborder(GdImage $image, int $x, int $y, int $border_color, int $color): true {} -function imagefill(GdImage $image, int $x, int $y, int $color): bool {} +function imagefill(GdImage $image, int $x, int $y, int $color): true {} function imagecolorstotal(GdImage $image): int {} @@ -697,27 +697,27 @@ function imagefontwidth(GdFont|int $font): int {} function imagefontheight(GdFont|int $font): int {} -function imagechar(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {} +function imagechar(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): true {} -function imagecharup(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {} +function imagecharup(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): true {} -function imagestring(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {} +function imagestring(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): true {} -function imagestringup(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {} +function imagestringup(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): true {} -function imagecopy(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height): bool {} +function imagecopy(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height): true {} -function imagecopymerge(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): bool {} +function imagecopymerge(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): true {} -function imagecopymergegray(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): bool {} +function imagecopymergegray(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): true {} -function imagecopyresized(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): bool {} +function imagecopyresized(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): true {} function imagesx(GdImage $image): int {} function imagesy(GdImage $image): int {} -function imagesetclip(GdImage $image, int $x1, int $y1, int $x2, int $y2): bool {} +function imagesetclip(GdImage $image, int $x1, int $y1, int $x2, int $y2): true {} /** * @return array @@ -756,9 +756,9 @@ function imagefilter(GdImage $image, int $filter, ...$args): bool {} function imageconvolution(GdImage $image, array $matrix, float $divisor, float $offset): bool {} -function imageflip(GdImage $image, int $mode): bool {} +function imageflip(GdImage $image, int $mode): true {} -function imageantialias(GdImage $image, bool $enable): bool {} +function imageantialias(GdImage $image, bool $enable): true {} /** @refcount 1 */ function imagecrop(GdImage $image, array $rectangle): GdImage|false {} @@ -793,4 +793,4 @@ function imagesetinterpolation(GdImage $image, int $method = IMG_BILINEAR_FIXED) * @return array|true * @refcount 1 */ -function imageresolution(GdImage $image, ?int $resolution_x = null, ?int $resolution_y = null): array|bool {} +function imageresolution(GdImage $image, ?int $resolution_x = null, ?int $resolution_y = null): array|true {} diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h index 02f57e52ba940..5cf4f2f29a9bd 100644 --- a/ext/gd/gd_arginfo.h +++ b/ext/gd/gd_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0f8a22bff1d123313f37da400500e573baace837 */ + * Stub hash: 94822f6472750c646fc138f383278ca692b39d27 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -30,17 +30,17 @@ ZEND_END_ARG_INFO() #define arginfo_imagepalettetotruecolor arginfo_imageistruecolor -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolormatch, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolormatch, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image1, GdImage, 0) ZEND_ARG_OBJ_INFO(0, image2, GdImage, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetthickness, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetthickness, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, thickness, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledellipse, 0, 6, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledellipse, 0, 6, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, center_x, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, center_y, IS_LONG, 0) @@ -49,7 +49,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledellipse, 0, 6, _IS_BO ZEND_ARG_TYPE_INFO(0, color, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledarc, 0, 9, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledarc, 0, 9, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, center_x, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, center_y, IS_LONG, 0) @@ -61,14 +61,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilledarc, 0, 9, _IS_BOOL, ZEND_ARG_TYPE_INFO(0, style, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagealphablending, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagealphablending, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0) ZEND_END_ARG_INFO() #define arginfo_imagesavealpha arginfo_imagealphablending -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagelayereffect, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagelayereffect, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, effect, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -93,7 +93,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagecolorexactalpha arginfo_imagecolorresolvealpha -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopyresampled, 0, 10, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopyresampled, 0, 10, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, dst_image, GdImage, 0) ZEND_ARG_OBJ_INFO(0, src_image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, dst_x, IS_LONG, 0) @@ -122,12 +122,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imagerotate, 0, 3, GdImage, ZEND_ARG_TYPE_INFO(0, background_color, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesettile, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesettile, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_OBJ_INFO(0, tile, GdImage, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetbrush, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetbrush, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_OBJ_INFO(0, brush, GdImage, 0) ZEND_END_ARG_INFO() @@ -274,7 +274,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagebmp, 0, 1, _IS_BOOL, 0) ZEND_END_ARG_INFO() #endif -#define arginfo_imagedestroy arginfo_imageistruecolor +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagedestroy, 0, 1, IS_TRUE, 0) + ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imagecolorallocate, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) @@ -303,7 +305,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagecolorclosesthwb arginfo_imagecolorclosest -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolordeallocate, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolordeallocate, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, color, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -326,20 +328,20 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolorsforindex, 0, 2, IS_AR ZEND_ARG_TYPE_INFO(0, color, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagegammacorrect, 0, 3, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagegammacorrect, 0, 3, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, input_gamma, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, output_gamma, IS_DOUBLE, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetpixel, 0, 4, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetpixel, 0, 4, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, color, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imageline, 0, 6, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imageline, 0, 6, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, x1, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, y1, IS_LONG, 0) @@ -354,7 +356,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagefilledrectangle arginfo_imageline -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagearc, 0, 8, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagearc, 0, 8, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, center_x, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, center_y, IS_LONG, 0) @@ -367,7 +369,7 @@ ZEND_END_ARG_INFO() #define arginfo_imageellipse arginfo_imagefilledellipse -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilltoborder, 0, 5, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefilltoborder, 0, 5, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) @@ -408,7 +410,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagefontheight arginfo_imagefontwidth -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagechar, 0, 6, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagechar, 0, 6, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL) ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) @@ -419,7 +421,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagecharup arginfo_imagechar -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagestring, 0, 6, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagestring, 0, 6, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL) ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) @@ -430,7 +432,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagestringup arginfo_imagestring -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopy, 0, 8, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopy, 0, 8, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, dst_image, GdImage, 0) ZEND_ARG_OBJ_INFO(0, src_image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, dst_x, IS_LONG, 0) @@ -441,7 +443,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopy, 0, 8, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, src_height, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopymerge, 0, 9, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecopymerge, 0, 9, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, dst_image, GdImage, 0) ZEND_ARG_OBJ_INFO(0, src_image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, dst_x, IS_LONG, 0) @@ -461,7 +463,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagesy arginfo_imagecolorstotal -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetclip, 0, 5, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetclip, 0, 5, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, x1, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, y1, IS_LONG, 0) @@ -512,7 +514,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imageconvolution, 0, 4, _IS_BOOL ZEND_ARG_TYPE_INFO(0, offset, IS_DOUBLE, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imageflip, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imageflip, 0, 2, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -561,7 +563,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagesetinterpolation, 0, 1, _IS ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, method, IS_LONG, 0, "IMG_BILINEAR_FIXED") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageresolution, 0, 1, MAY_BE_ARRAY|MAY_BE_BOOL) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageresolution, 0, 1, MAY_BE_ARRAY|MAY_BE_TRUE) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resolution_x, IS_LONG, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resolution_y, IS_LONG, 1, "null") From 80ea28e918e02bc01381ea0ba1b9e3851ab82c9d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:25:51 +0100 Subject: [PATCH 288/503] ext/gd: Remove useless ext/standard header include --- ext/gd/gd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 8a6d6b596358a..464e3619333c7 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -27,7 +27,6 @@ #include "php.h" #include "php_ini.h" -#include "ext/standard/head.h" #include #include "SAPI.h" #include "php_gd.h" From 9491c6850bada23f241c66dbdcca2bf38a853ee9 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:15:47 +0100 Subject: [PATCH 289/503] ext/gd: Use uint32_t type instead of int type --- ext/gd/gd.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 464e3619333c7..8bd7584d551ae 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3712,7 +3712,7 @@ PHP_FUNCTION(imageconvolution) zval *var = NULL, *var2 = NULL; gdImagePtr im_src = NULL; double div, offset; - int nelem, i, j, res; + int i, j, res; float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; ZEND_PARSE_PARAMETERS_START(4, 4) @@ -3724,8 +3724,7 @@ PHP_FUNCTION(imageconvolution) im_src = php_gd_libgdimageptr_from_zval_p(SIM); - nelem = zend_hash_num_elements(Z_ARRVAL_P(hash_matrix)); - if (nelem != 3) { + if (zend_hash_num_elements(Z_ARRVAL_P(hash_matrix)) != 3) { zend_argument_value_error(2, "must be a 3x3 array"); RETURN_THROWS(); } @@ -4045,7 +4044,6 @@ PHP_FUNCTION(imageaffine) zval *z_affine; zval *tmp; double affine[6]; - int i, nelems; zval *zval_affine_elem = NULL; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -4057,13 +4055,13 @@ PHP_FUNCTION(imageaffine) src = php_gd_libgdimageptr_from_zval_p(IM); - - if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) { + uint32_t nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine)); + if (nelems != 6) { zend_argument_value_error(2, "must have 6 elements"); RETURN_THROWS(); } - for (i = 0; i < nelems; i++) { + for (uint32_t i = 0; i < nelems; i++) { if ((zval_affine_elem = zend_hash_index_find_deref(Z_ARRVAL_P(z_affine), i)) != NULL) { switch (Z_TYPE_P(zval_affine_elem)) { case IS_LONG: From be93f29f2f3ea4528cd653e4b033bfb71052bf97 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:17:40 +0100 Subject: [PATCH 290/503] ext/gd: Reduce scope of variables --- ext/gd/gd.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 8bd7584d551ae..cc2af5f66d3f7 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -1753,7 +1753,6 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, cons char *file = NULL; zend_long quality = 128, type = 1; gdImagePtr im; - FILE *fp; size_t file_len = 0; /* The quality parameter for gd2 stands for chunk size */ @@ -1783,7 +1782,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, cons if (file_len) { PHP_GD_CHECK_OPEN_BASEDIR(file, "Invalid filename"); - fp = VCWD_FOPEN(file, "wb"); + FILE *fp = VCWD_FOPEN(file, "wb"); if (!fp) { php_error_docref(NULL, E_WARNING, "Unable to open \"%s\" for writing", file); RETURN_FALSE; @@ -1851,9 +1850,7 @@ PHP_FUNCTION(imagexbm) zend_long foreground_color; bool foreground_color_is_null = true; gdImagePtr im; - int i; gdIOCtx *ctx = NULL; - php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_OBJECT_OF_CLASS(imgind, gd_image_ce) @@ -1865,7 +1862,7 @@ PHP_FUNCTION(imagexbm) im = php_gd_libgdimageptr_from_zval_p(imgind); if (file != NULL) { - stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH, NULL); + php_stream *stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH, NULL); if (stream == NULL) { RETURN_FALSE; } @@ -1876,6 +1873,7 @@ PHP_FUNCTION(imagexbm) } if (foreground_color_is_null) { + int i; for (i = 0; i < gdImageColorsTotal(im); i++) { if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) { break; @@ -2083,7 +2081,6 @@ PHP_FUNCTION(imagewbmp) zend_long foreground_color; bool foreground_color_is_null = true; gdImagePtr im; - int i; gdIOCtx *ctx; zval *to_zval = NULL; @@ -2102,6 +2099,7 @@ PHP_FUNCTION(imagewbmp) } if (foreground_color_is_null) { + int i; for (i = 0; i < gdImageColorsTotal(im); i++) { if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) { break; @@ -2462,7 +2460,6 @@ PHP_FUNCTION(imagegammacorrect) { zval *IM; gdImagePtr im; - int i; double input, output, gamma; ZEND_PARSE_PARAMETERS_START(3, 3) @@ -2486,11 +2483,9 @@ PHP_FUNCTION(imagegammacorrect) im = php_gd_libgdimageptr_from_zval_p(IM); if (gdImageTrueColor(im)) { - int x, y, c; - - for (y = 0; y < gdImageSY(im); y++) { - for (x = 0; x < gdImageSX(im); x++) { - c = gdImageGetPixel(im, x, y); + for (int y = 0; y < gdImageSY(im); y++) { + for (int x = 0; x < gdImageSX(im); x++) { + int c = gdImageGetPixel(im, x, y); gdImageSetPixel(im, x, y, gdTrueColorAlpha( (int) ((pow((gdTrueColorGetRed(c) / 255.0), gamma) * 255) + .5), @@ -2504,7 +2499,7 @@ PHP_FUNCTION(imagegammacorrect) RETURN_TRUE; } - for (i = 0; i < gdImageColorsTotal(im); i++) { + for (int i = 0; i < gdImageColorsTotal(im); i++) { im->red[i] = (int)((pow((im->red[i] / 255.0), gamma) * 255) + .5); im->green[i] = (int)((pow((im->green[i] / 255.0), gamma) * 255) + .5); im->blue[i] = (int)((pow((im->blue[i] / 255.0), gamma) * 255) + .5); @@ -2810,7 +2805,7 @@ static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) zval *var = NULL; gdImagePtr im; gdPointPtr points; - int npoints, col, nelem, i; + int npoints, col, nelem; ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce) @@ -2850,7 +2845,7 @@ static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) points = (gdPointPtr) safe_emalloc(npoints, sizeof(gdPoint), 0); - for (i = 0; i < npoints; i++) { + for (int i = 0; i < npoints; i++) { if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2))) != NULL) { points[i].x = zval_get_long(var); } @@ -3712,7 +3707,7 @@ PHP_FUNCTION(imageconvolution) zval *var = NULL, *var2 = NULL; gdImagePtr im_src = NULL; double div, offset; - int i, j, res; + int res; float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; ZEND_PARSE_PARAMETERS_START(4, 4) @@ -3729,14 +3724,14 @@ PHP_FUNCTION(imageconvolution) RETURN_THROWS(); } - for (i=0; i<3; i++) { + for (uint8_t i = 0; i < 3; i++) { if ((var = zend_hash_index_find_deref(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) { if (zend_hash_num_elements(Z_ARRVAL_P(var)) != 3 ) { zend_argument_value_error(2, "must be a 3x3 array, matrix[%d] only has %d elements", i, zend_hash_num_elements(Z_ARRVAL_P(var))); RETURN_THROWS(); } - for (j=0; j<3; j++) { + for (uint8_t j = 0; j < 3; j++) { if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), j)) != NULL) { matrix[i][j] = (float) zval_get_double(var2); } else { @@ -4042,9 +4037,7 @@ PHP_FUNCTION(imageaffine) gdRectPtr pRect = NULL; zval *z_rect = NULL; zval *z_affine; - zval *tmp; double affine[6]; - zval *zval_affine_elem = NULL; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce) @@ -4062,7 +4055,8 @@ PHP_FUNCTION(imageaffine) } for (uint32_t i = 0; i < nelems; i++) { - if ((zval_affine_elem = zend_hash_index_find_deref(Z_ARRVAL_P(z_affine), i)) != NULL) { + zval *zval_affine_elem = zend_hash_index_find_deref(Z_ARRVAL_P(z_affine), i); + if (zval_affine_elem != NULL) { switch (Z_TYPE_P(zval_affine_elem)) { case IS_LONG: case IS_DOUBLE: @@ -4081,6 +4075,7 @@ PHP_FUNCTION(imageaffine) } if (z_rect != NULL) { + zval *tmp; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "x", sizeof("x") - 1)) != NULL) { rect.x = zval_get_long(tmp); } else { @@ -4130,7 +4125,7 @@ PHP_FUNCTION(imageaffinematrixget) zend_long type; zval *options = NULL; zval *tmp; - int res = GD_FALSE, i; + int res = GD_FALSE; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(type) @@ -4194,7 +4189,7 @@ PHP_FUNCTION(imageaffinematrixget) RETURN_FALSE; } else { array_init(return_value); - for (i = 0; i < 6; i++) { + for (uint8_t i = 0; i < 6; i++) { add_index_double(return_value, i, affine[i]); } } From b647716199c8e99188e58bf4aa210b8adf27903d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:44:58 +0100 Subject: [PATCH 291/503] ext/gd: Use RETURN_BOOL() where applicable Instead of an if/else --- ext/gd/gd.c | 87 +++++++++-------------------------------------------- 1 file changed, 14 insertions(+), 73 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index cc2af5f66d3f7..be0961578a611 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -751,11 +751,7 @@ PHP_FUNCTION(imagepalettetotruecolor) im = php_gd_libgdimageptr_from_zval_p(IM); - if (gdImagePaletteToTrueColor(im) == 0) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(gdImagePaletteToTrueColor(im) != 0); } /* }}} */ @@ -3424,22 +3420,14 @@ static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageNegate(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageNegate(im_src) == 1); } static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageGrayScale(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageGrayScale(im_src) == 1); } static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS) @@ -3456,11 +3444,7 @@ static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS) im_src = php_gd_libgdimageptr_from_zval_p(SIM); - if (gdImageBrightness(im_src, (int)brightness) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageBrightness(im_src, (int)brightness) == 1); } static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS) @@ -3477,11 +3461,7 @@ static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS) im_src = php_gd_libgdimageptr_from_zval_p(SIM); - if (gdImageContrast(im_src, (int)contrast) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageContrast(im_src, (int)contrast) == 1); } static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS) @@ -3503,66 +3483,42 @@ static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS) im_src = php_gd_libgdimageptr_from_zval_p(SIM); - if (gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1); } static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageEdgeDetectQuick(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageEdgeDetectQuick(im_src) == 1); } static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageEmboss(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageEmboss(im_src) == 1); } static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageGaussianBlur(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageGaussianBlur(im_src) == 1); } static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageSelectiveBlur(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageSelectiveBlur(im_src) == 1); } static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS) { PHP_GD_SINGLE_RES - if (gdImageMeanRemoval(im_src) == 1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageMeanRemoval(im_src) == 1); } static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS) @@ -3580,11 +3536,7 @@ static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS) im_src = php_gd_libgdimageptr_from_zval_p(SIM); - if (gdImageSmooth(im_src, (float)weight)==1) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImageSmooth(im_src, (float)weight) == 1); } static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS) @@ -3604,11 +3556,7 @@ static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS) im = php_gd_libgdimageptr_from_zval_p(IM); - if (gdImagePixelate(im, (int) blocksize, (const unsigned int) mode)) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(gdImagePixelate(im, (int) blocksize, (const unsigned int) mode));; } static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS) @@ -3707,7 +3655,6 @@ PHP_FUNCTION(imageconvolution) zval *var = NULL, *var2 = NULL; gdImagePtr im_src = NULL; double div, offset; - int res; float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; ZEND_PARSE_PARAMETERS_START(4, 4) @@ -3758,13 +3705,7 @@ PHP_FUNCTION(imageconvolution) RETURN_THROWS(); } - res = gdImageConvolution(im_src, matrix, div_float, (float) offset); - - if (res) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(gdImageConvolution(im_src, matrix, div_float, (float) offset)); } /* }}} */ /* End section: Filters */ From 7a7b388401d84fe6caf2c702759bce267d1eb41f Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Apr 2025 21:56:22 +0100 Subject: [PATCH 292/503] ext/gd: Move FREETYPE defines into the ifdef --- ext/gd/gd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index be0961578a611..9017d58bd75aa 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3311,10 +3311,11 @@ PHP_FUNCTION(imagegetclip) } /* }}} */ +#ifdef HAVE_GD_FREETYPE + #define TTFTEXT_DRAW 0 #define TTFTEXT_BBOX 1 -#ifdef HAVE_GD_FREETYPE /* {{{ Give the bounding box of a text using fonts via freetype2 */ PHP_FUNCTION(imageftbbox) { From fed948dbd48f247de8181a127835adf1ff725794 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 4 Apr 2025 20:48:57 +0100 Subject: [PATCH 293/503] Fixed GH-18247: dba_popen() memory leak on invalid path. and a handful more error code paths. close GH-18250 --- NEWS | 3 +++ ext/dba/dba.c | 25 +++++++++++++------------ ext/dba/tests/gh18247.phpt | 12 ++++++++++++ 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 ext/dba/tests/gh18247.phpt diff --git a/NEWS b/NEWS index d04c454e35b92..f3a314498bbbc 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS . Fixed bug GH-18038 (Lazy proxy calls magic methods twice). (Arnaud) . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) +- DBA: + . FIxed bug GH-18247 dba_popen() memory leak on invalid path. (David Carlier) + - GD: . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage in gdImageCrop(). (David Carlier) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 2205b13dfe050..7982e4255b07c 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -864,9 +864,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } if (!connection->info->lock.fp) { /* stream operation already wrote an error message */ - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } if (!error && !php_stream_supports_lock(connection->info->lock.fp)) { error = "Stream does not support locking"; @@ -885,9 +883,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } if (!connection->info->fp) { /* stream operation already wrote an error message */ - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) { /* Needed because some systems do not allow to write to the original @@ -895,9 +891,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) */ if (SUCCESS != php_stream_cast(connection->info->fp, PHP_STREAM_AS_FD, (void*)&connection->info->fd, 1)) { php_error_docref(NULL, E_WARNING, "Could not cast stream"); - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; #ifdef F_SETFL } else if (modenr == DBA_CREAT) { int flags = fcntl(connection->info->fd, F_GETFL); @@ -931,9 +925,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s", hptr->name); } } - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } connection->info->hnd = hptr; @@ -942,6 +934,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) if (zend_register_persistent_resource(resource_key, resource_key_len, connection->info, le_pdb) == NULL) { php_error_docref(NULL, E_WARNING, "Could not register persistent resource"); efree(resource_key); + dba_close_connection(connection); zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -949,6 +942,14 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) zend_hash_add_new(&DBA_G(connections), connection->hash, return_value); efree(resource_key); + return; +fail: + efree(resource_key); + zend_string_release_ex(connection->hash, persistent); + dba_close_info(connection->info); + connection->info = NULL; + zval_ptr_dtor(return_value); + RETURN_FALSE; } /* }}} */ diff --git a/ext/dba/tests/gh18247.phpt b/ext/dba/tests/gh18247.phpt new file mode 100644 index 0000000000000..bb757452321d9 --- /dev/null +++ b/ext/dba/tests/gh18247.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-18247: dba_open() memory leak on invalid path +--EXTENSIONS-- +dba +--FILE-- + +--EXPECTF-- + +Warning: dba_popen(/inexistent): Failed to open stream: No such file or directory in %s on line %d +bool(false) From 633400bb56c875076b2d9daba0c5017b7806ddf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 6 Apr 2025 18:56:57 +0200 Subject: [PATCH 294/503] mysqlnd: Make `st_mysqlnd_stats.values` a dynamic struct member (#18246) This avoids another separate allocation. --- ext/mysqlnd/mysqlnd_statistics.c | 5 ++--- ext/mysqlnd/mysqlnd_structs.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c index c6f7b2bab5b72..0d94303ea3669 100644 --- a/ext/mysqlnd/mysqlnd_statistics.c +++ b/ext/mysqlnd/mysqlnd_statistics.c @@ -214,8 +214,8 @@ mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, const MYSQLND_STRING PHPAPI void mysqlnd_stats_init(MYSQLND_STATS ** stats, const size_t statistic_count, const bool persistent) { - *stats = pecalloc(1, sizeof(MYSQLND_STATS), persistent); - (*stats)->values = pecalloc(statistic_count, sizeof(uint64_t), persistent); + size_t size = zend_safe_address_guarded(statistic_count, sizeof(*(*stats)->values), sizeof(**stats)); + *stats = pecalloc(1, size, persistent); (*stats)->count = statistic_count; #ifdef ZTS (*stats)->LOCK_access = tsrm_mutex_alloc(); @@ -231,7 +231,6 @@ mysqlnd_stats_end(MYSQLND_STATS * stats, const bool persistent) #ifdef ZTS tsrm_mutex_free(stats->LOCK_access); #endif - pefree(stats->values, persistent); /* mnd_free will reference LOCK_access and crash...*/ pefree(stats, persistent); } diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index cf99ac706239c..b0c9f3a37d6e2 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -297,11 +297,11 @@ typedef struct st_mysqlnd_stats MYSQLND_STATS; struct st_mysqlnd_stats { - uint64_t *values; size_t count; #ifdef ZTS MUTEX_T LOCK_access; #endif + uint64_t values[] ZEND_ELEMENT_COUNT(count); }; From ea6f2fbe92179e8a898e81204c2ee58e46a4e22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 7 Apr 2025 10:51:30 +0200 Subject: [PATCH 295/503] [skip ci] Request the output of `php -v` in the `bug_report.yml` issue template (#18230) The output of `php -v` immediately shows whether OPcache is loaded and whether PHP is a NTS/ZTS and Debug/Release build. --- .github/ISSUE_TEMPLATE/bug_report.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index acd9c1220c20e..f0f80bd98e324 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -22,15 +22,22 @@ body: ``` validations: required: true - - type: input + - type: textarea attributes: label: PHP Version - description: "The used PHP version. Make sure it is [supported](https://www.php.net/supported-versions.php)." - placeholder: "PHP 8.0.12" + description: | + Please run PHP with the `-v` flag (e.g. `php -v`, `php8.3 -v`, `php-fpm -v` or similar) and provide the full output of that command. If executing that command is not possible, please provide the full version number as given in PHPInfo. + + Please make sure that the used PHP version [is a supported version](https://www.php.net/supported-versions.php). + placeholder: | + PHP 8.3.19 (cli) (built: Mar 13 2025 17:44:40) (NTS) + Copyright (c) The PHP Group + Zend Engine v4.3.19, Copyright (c) Zend Technologies + with Zend OPcache v8.3.19, Copyright (c), by Zend Technologies validations: required: true - type: input attributes: label: Operating System description: "The used operating system, if relevant." - placeholder: "Ubuntu 20.04" + placeholder: "Ubuntu 24.04" From 71da944c82de526226b3e31a62937c089490f957 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 5 Apr 2025 17:15:48 +0100 Subject: [PATCH 296/503] Zend: Add MUTABLE zend_type foreach macros and const qualifiers The motivation for this is that types should be considered immutable. The only times this is not valid is during compilation, optimizations (opcache), or destruction. Therefore the "normal" type foreach macros are marked to take const arguments and we add mutable version that say so in the name. Thus add various const qualifiers to communicate intent. --- Zend/Optimizer/compact_literals.c | 2 +- Zend/Optimizer/dfa_pass.c | 8 +-- Zend/zend_API.c | 4 +- Zend/zend_compile.c | 30 +++++----- Zend/zend_execute.c | 94 +++++++++++++++---------------- Zend/zend_execute.h | 18 +++--- Zend/zend_inheritance.c | 32 +++++------ Zend/zend_opcode.c | 2 +- Zend/zend_types.h | 25 +++++++- ext/opcache/ZendAccelerator.c | 2 +- ext/opcache/zend_file_cache.c | 4 +- ext/opcache/zend_persist.c | 2 +- ext/opcache/zend_persist_calc.c | 2 +- ext/reflection/php_reflection.c | 4 +- 14 files changed, 125 insertions(+), 104 deletions(-) diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index db973572aca3a..202cb7c2d6114 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -69,7 +69,7 @@ static size_t type_num_classes(const zend_op_array *op_array, uint32_t arg_num) } ZEND_ASSERT(ZEND_TYPE_IS_UNION(arg_info->type)); size_t count = 0; - zend_type *list_type; + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index 2c3aaae065997..bf85764c93b49 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -254,7 +254,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op free_alloca(shiftlist, use_heap); } -static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { +static bool safe_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) { if (ce1 == ce2) { return 1; } @@ -267,9 +267,9 @@ static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { static inline bool can_elide_list_type( const zend_script *script, const zend_op_array *op_array, - const zend_ssa_var_info *use_info, zend_type type) + const zend_ssa_var_info *use_info, const zend_type type) { - zend_type *single_type; + const zend_type *single_type; /* For intersection: result==false is failure, default is success. * For union: result==true is success, default is failure. */ bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type); @@ -280,7 +280,7 @@ static inline bool can_elide_list_type( } if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type)); - zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); + const zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); zend_string_release(lcname); bool result = ce && safe_instanceof(use_info->ce, ce); if (result == !is_intersection) { diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 4c31fba5e506e..e0006e7d7275f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2914,14 +2914,14 @@ static zend_always_inline void zend_normalize_internal_type(zend_type *type) { ZEND_ASSERT(!ZEND_TYPE_CONTAINS_CODE(*type, IS_RESOURCE) && "resource is not allowed in a zend_type"); } zend_type *current; - ZEND_TYPE_FOREACH(*type, current) { + ZEND_TYPE_FOREACH_MUTABLE(*type, current) { if (ZEND_TYPE_HAS_NAME(*current)) { zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*current)); zend_alloc_ce_cache(name); ZEND_TYPE_SET_PTR(*current, name); } else if (ZEND_TYPE_HAS_LIST(*current)) { zend_type *inner; - ZEND_TYPE_FOREACH(*current, inner) { + ZEND_TYPE_FOREACH_MUTABLE(*current, inner) { ZEND_ASSERT(!ZEND_TYPE_HAS_LITERAL_NAME(*inner) && !ZEND_TYPE_HAS_LIST(*inner)); if (ZEND_TYPE_HAS_NAME(*inner)) { zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*inner)); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2e405de30ea62..3fa4c3959cb43 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1407,10 +1407,10 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop } static zend_string *add_intersection_type(zend_string *str, - zend_type_list *intersection_type_list, zend_class_entry *scope, + const zend_type_list *intersection_type_list, zend_class_entry *scope, bool is_bracketed) { - zend_type *single_type; + const zend_type *single_type; zend_string *intersection_str = NULL; ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) { @@ -1432,7 +1432,7 @@ static zend_string *add_intersection_type(zend_string *str, return str; } -zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { +zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry *scope) { zend_string *str = NULL; /* Pure intersection type */ @@ -1441,7 +1441,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false); } else if (ZEND_TYPE_HAS_LIST(type)) { /* A union type might not be a list */ - zend_type *list_type; + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true); @@ -1527,7 +1527,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type) { return zend_type_to_string_resolved(type, NULL); } -static bool is_generator_compatible_class_type(zend_string *name) { +static bool is_generator_compatible_class_type(const zend_string *name) { return zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_TRAVERSABLE)) || zend_string_equals_literal_ci(name, "Iterator") || zend_string_equals_literal_ci(name, "Generator"); @@ -1541,10 +1541,10 @@ static void zend_mark_function_as_generator(void) /* {{{ */ } if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - zend_type return_type = CG(active_op_array)->arg_info[-1].type; + const zend_type return_type = CG(active_op_array)->arg_info[-1].type; bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_OBJECT) != 0; if (!valid_type) { - zend_type *single_type; + const zend_type *single_type; ZEND_TYPE_FOREACH(return_type, single_type) { if (ZEND_TYPE_HAS_NAME(*single_type) && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) { @@ -2621,7 +2621,7 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ /* }}} */ /* Remember to update type_num_classes() in compact_literals.c when changing this function */ -static size_t zend_type_get_num_classes(zend_type type) { +static size_t zend_type_get_num_classes(const zend_type type) { if (!ZEND_TYPE_IS_COMPLEX(type)) { return 0; } @@ -2632,7 +2632,7 @@ static size_t zend_type_get_num_classes(zend_type type) { } ZEND_ASSERT(ZEND_TYPE_IS_UNION(type)); size_t count = 0; - zend_type *list_type; + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { @@ -7048,7 +7048,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast) } } -static void zend_are_intersection_types_redundant(zend_type left_type, zend_type right_type) +static void zend_are_intersection_types_redundant(const zend_type left_type, const zend_type right_type) { ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type)); ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type)); @@ -7067,9 +7067,9 @@ static void zend_are_intersection_types_redundant(zend_type left_type, zend_type } unsigned int sum = 0; - zend_type *outer_type; + const zend_type *outer_type; ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type) - zend_type *inner_type; + const zend_type *inner_type; ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type) if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) { sum++; @@ -7098,12 +7098,12 @@ static void zend_are_intersection_types_redundant(zend_type left_type, zend_type } } -static void zend_is_intersection_type_redundant_by_single_type(zend_type intersection_type, zend_type single_type) +static void zend_is_intersection_type_redundant_by_single_type(const zend_type intersection_type, const zend_type single_type) { ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(intersection_type)); ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type)); - zend_type *single_intersection_type = NULL; + const zend_type *single_intersection_type = NULL; ZEND_TYPE_FOREACH(intersection_type, single_intersection_type) if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) { zend_string *single_type_str = zend_type_to_string(single_type); @@ -7115,7 +7115,7 @@ static void zend_is_intersection_type_redundant_by_single_type(zend_type interse } /* Used by both intersection and union types prior to transforming the type list to a full zend_type */ -static void zend_is_type_list_redundant_by_single_type(zend_type_list *type_list, zend_type type) +static void zend_is_type_list_redundant_by_single_type(const zend_type_list *type_list, const zend_type type) { ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(type)); for (size_t i = 0; i < type_list->num_types - 1; i++) { diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4fed2af3a92fd..786cd60ef1401 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -609,7 +609,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg zend_string_release(func_name); } -static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(zend_property_info *prop) { +static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(const zend_property_info *prop) { zend_string *type_str = zend_type_to_string(prop->type); zend_type_error( "Cannot auto-initialize an array inside property %s::$%s of type %s", @@ -619,7 +619,7 @@ static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(zend_ zend_string_release(type_str); } -static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(zend_property_info *prop) { +static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(const zend_property_info *prop) { zend_string *type_str = zend_type_to_string(prop->type); zend_type_error( "Cannot auto-initialize an array inside a reference held by property %s::$%s of type %s", @@ -630,7 +630,7 @@ static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(zend_p } static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_error( - zend_property_info *prop) { + const zend_property_info *prop) { zend_throw_error(NULL, "Cannot access uninitialized non-nullable property %s::$%s by reference", ZSTR_VAL(prop->ce->name), @@ -638,7 +638,7 @@ static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_err } /* this should modify object only if it's empty */ -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(const zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) { zend_string *tmp_property_name; zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); @@ -673,7 +673,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_erro } static ZEND_COLD void zend_verify_type_error_common( - const zend_function *zf, const zend_arg_info *arg_info, zval *value, + const zend_function *zf, const zend_arg_info *arg_info, const zval *value, const char **fname, const char **fsep, const char **fclass, zend_string **need_msg, const char **given_kind) { @@ -696,9 +696,9 @@ static ZEND_COLD void zend_verify_type_error_common( } ZEND_API ZEND_COLD void zend_verify_arg_error( - const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value) + const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, const zval *value) { - zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; + const zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; const char *fname, *fsep, *fclass; zend_string *need_msg; const char *given_msg; @@ -909,7 +909,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modificati ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name)); } -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(uint8_t type) +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(const uint8_t type) { zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(type)); } @@ -975,9 +975,9 @@ static zend_always_inline const zend_class_entry *zend_ce_from_type( } static bool zend_check_intersection_for_property_or_class_constant_class_type( - const zend_class_entry *scope, zend_type_list *intersection_type_list, const zend_class_entry *value_ce) + const zend_class_entry *scope, const zend_type_list *intersection_type_list, const zend_class_entry *value_ce) { - zend_type *list_type; + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) { ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); @@ -990,13 +990,13 @@ static bool zend_check_intersection_for_property_or_class_constant_class_type( } static bool zend_check_and_resolve_property_or_class_constant_class_type( - const zend_class_entry *scope, zend_type member_type, const zend_class_entry *value_ce) { + const zend_class_entry *scope, const zend_type member_type, const zend_class_entry *value_ce) { if (ZEND_TYPE_HAS_LIST(member_type)) { - zend_type *list_type; if (ZEND_TYPE_IS_INTERSECTION(member_type)) { return zend_check_intersection_for_property_or_class_constant_class_type( scope, ZEND_TYPE_LIST(member_type), value_ce); } else { + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(member_type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { if (zend_check_intersection_for_property_or_class_constant_class_type( @@ -1059,7 +1059,7 @@ ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_in return i_zend_verify_property_type(info, property, strict); } -static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value, zend_refcounted **garbage_ptr EXECUTE_DATA_DC) +static zend_never_inline zval* zend_assign_to_typed_prop(const zend_property_info *info, zval *property_val, zval *value, zend_refcounted **garbage_ptr EXECUTE_DATA_DC) { zval tmp; @@ -1087,7 +1087,7 @@ static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *inf return zend_assign_to_variable_ex(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr); } -static zend_always_inline bool zend_value_instanceof_static(zval *zv) { +static zend_always_inline bool zend_value_instanceof_static(const zval *zv) { if (Z_TYPE_P(zv) != IS_OBJECT) { return 0; } @@ -1110,7 +1110,7 @@ static zend_always_inline bool zend_value_instanceof_static(zval *zv) { #define PROGRESS_CACHE_SLOT() if (HAVE_CACHE_SLOT) {cache_slot++;} static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot( - void **cache_slot, zend_type *type) + void **cache_slot, const zend_type *type) { if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) { return (zend_class_entry *) *cache_slot; @@ -1140,17 +1140,18 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot( return ce; } -static bool zend_check_intersection_type_from_cache_slot(zend_type_list *intersection_type_list, - zend_class_entry *arg_ce, void ***cache_slot_ptr) +static bool zend_check_intersection_type_from_cache_slot( + const zend_type_list *intersection_type_list, + const zend_class_entry *arg_ce, + void ***cache_slot_ptr) { void **cache_slot = *cache_slot_ptr; - zend_class_entry *ce; - zend_type *list_type; + const zend_type *list_type; bool status = true; ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) { /* Only check classes if the type might be valid */ if (status) { - ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); + zend_class_entry *ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); /* If type is not an instance of one of the types taking part in the * intersection it cannot be a valid instance of the whole intersection type. */ if (!ce || !instanceof_function(arg_ce, ce)) { @@ -1166,17 +1167,16 @@ static bool zend_check_intersection_type_from_cache_slot(zend_type_list *interse } static zend_always_inline bool zend_check_type_slow( - zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type, bool is_internal) { - uint32_t type_mask; if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { zend_class_entry *ce; if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) { - zend_type *list_type; if (ZEND_TYPE_IS_INTERSECTION(*type)) { return zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg), &cache_slot); } else { + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), &cache_slot)) { @@ -1204,7 +1204,7 @@ static zend_always_inline bool zend_check_type_slow( } } - type_mask = ZEND_TYPE_FULL_MASK(*type); + const uint32_t type_mask = ZEND_TYPE_FULL_MASK(*type); if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, is_internal ? IS_CALLABLE_SUPPRESS_DEPRECATIONS : 0, NULL)) { return 1; @@ -1232,10 +1232,10 @@ static zend_always_inline bool zend_check_type_slow( } static zend_always_inline bool zend_check_type( - zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope, + const zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope, bool is_return_type, bool is_internal) { - zend_reference *ref = NULL; + const zend_reference *ref = NULL; ZEND_ASSERT(ZEND_TYPE_IS_SET(*type)); if (UNEXPECTED(Z_ISREF_P(arg))) { @@ -1251,15 +1251,15 @@ static zend_always_inline bool zend_check_type( } ZEND_API bool zend_check_user_type_slow( - zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, bool is_return_type) + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type) { return zend_check_type_slow( type, arg, ref, cache_slot, is_return_type, /* is_internal */ false); } -static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) +static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) { - zend_arg_info *cur_arg_info; + const zend_arg_info *cur_arg_info; ZEND_ASSERT(arg_num <= zf->common.num_args); cur_arg_info = &zf->common.arg_info[arg_num-1]; @@ -1274,7 +1274,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint } static zend_always_inline bool zend_verify_variadic_arg_type( - zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) + const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { @@ -1285,7 +1285,7 @@ static zend_always_inline bool zend_verify_variadic_arg_type( return 1; } -static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call) +static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_types(const zend_function *fbc, zend_execute_data *call) { uint32_t i; uint32_t num_args = ZEND_CALL_NUM_ARGS(call); @@ -1314,7 +1314,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ /* Determine whether an internal call should throw, because the passed arguments violate * an arginfo constraint. This is only checked in debug builds. In release builds, we * trust that arginfo matches what is enforced by zend_parse_parameters. */ -ZEND_API bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call) +ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call) { if (fbc->internal_function.handler == ZEND_FN(pass) || (fbc->internal_function.fn_flags & ZEND_ACC_FAKE_CLOSURE)) { /* Be lenient about the special pass function and about fake closures. */ @@ -1341,7 +1341,7 @@ ZEND_API bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_d return 0; } -ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc) +ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(const zend_function *fbc) { zend_error_noreturn(E_ERROR, "Arginfo / zpp mismatch during call of %s%s%s()", fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "", @@ -1353,10 +1353,10 @@ ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc) # define ZEND_VERIFY_FUNC_INFO 0 #endif -static void zend_verify_internal_func_info(zend_function *fn, zval *retval) { +static void zend_verify_internal_func_info(const zend_function *fn, const zval *retval) { #if ZEND_VERIFY_FUNC_INFO zend_string *name = fn->common.function_name; - uint32_t type_mask = zend_get_internal_func_info(fn, NULL, NULL); + const uint32_t type_mask = zend_get_internal_func_info(fn, NULL, NULL); if (!type_mask) { return; } @@ -1371,14 +1371,14 @@ static void zend_verify_internal_func_info(zend_function *fn, zval *retval) { } } - uint32_t type = 1u << Z_TYPE_P(retval); + const uint32_t type = 1u << Z_TYPE_P(retval); if (!(type_mask & type)) { zend_error_noreturn(E_CORE_ERROR, "%s() missing type %s", ZSTR_VAL(name), zend_get_type_by_const(Z_TYPE_P(retval))); } if (Z_TYPE_P(retval) == IS_ARRAY) { - HashTable *ht = Z_ARRVAL_P(retval); + const HashTable *ht = Z_ARRVAL_P(retval); uint32_t num_checked = 0; zend_string *str; zval *val; @@ -1395,7 +1395,7 @@ static void zend_verify_internal_func_info(zend_function *fn, zval *retval) { } } - uint32_t array_type = 1u << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT); + const uint32_t array_type = 1u << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT); if (!(type_mask & array_type)) { zend_error_noreturn(E_CORE_ERROR, "%s() missing array element type %s", @@ -1412,9 +1412,9 @@ static void zend_verify_internal_func_info(zend_function *fn, zval *retval) { } #endif -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data) +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(const zend_execute_data *execute_data) { - zend_execute_data *ptr = EX(prev_execute_data); + const zend_execute_data *ptr = EX(prev_execute_data); if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected", @@ -1437,7 +1437,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data * } } -ZEND_API ZEND_COLD void zend_verify_return_error(const zend_function *zf, zval *value) +ZEND_API ZEND_COLD void zend_verify_return_error(const zend_function *zf, const zval *value) { const zend_arg_info *arg_info = &zf->common.arg_info[-1]; const char *fname, *fsep, *fclass; @@ -1464,7 +1464,7 @@ ZEND_API ZEND_COLD void zend_verify_never_error(const zend_function *zf) } #if ZEND_DEBUG -static ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf, zval *value) +static ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf, const zval *value) { const zend_arg_info *arg_info = &zf->common.arg_info[-1]; const char *fname, *fsep, *fclass; @@ -1496,9 +1496,9 @@ static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, con fclass, fsep, fname, returned_msg, returned_kind); } -ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret) +ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *ret) { - zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1; + const zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1; if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) { if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) { @@ -1523,7 +1523,7 @@ static ZEND_COLD void zend_verify_missing_return_type(const zend_function *zf) zend_verify_return_error(zf, NULL); } -static zend_always_inline bool zend_check_class_constant_type(zend_class_constant *c, zval *constant) +static zend_always_inline bool zend_check_class_constant_type(const zend_class_constant *c, zval *constant) { ZEND_ASSERT(!Z_ISREF_P(constant)); if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(c->type, Z_TYPE_P(constant)))) { @@ -1540,7 +1540,7 @@ static zend_always_inline bool zend_check_class_constant_type(zend_class_constan return zend_verify_scalar_type_hint(type_mask, constant, true, false); } -ZEND_API bool zend_never_inline zend_verify_class_constant_type(zend_class_constant *c, const zend_string *name, zval *constant) +ZEND_API bool zend_never_inline zend_verify_class_constant_type(const zend_class_constant *c, const zend_string *name, zval *constant) { if (!zend_check_class_constant_type(c, constant)) { zend_verify_class_constant_type_error(c, name, constant); @@ -1709,7 +1709,7 @@ static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *re } } -static zend_never_inline void zend_binary_assign_op_typed_prop(zend_property_info *prop_info, zval *zptr, zval *value OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_binary_assign_op_typed_prop(const zend_property_info *prop_info, zval *zptr, zval *value OPLINE_DC EXECUTE_DATA_DC) { zval z_copy; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index e96a217a2904f..75c2d07e5e5cb 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -60,7 +60,7 @@ ZEND_API zend_result zend_eval_stringl_ex(const char *str, size_t str_len, zval /* export zend_pass_function to allow comparisons against it */ extern ZEND_API const zend_internal_function zend_pass_function; -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(const zend_execute_data *execute_data); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name); @@ -95,23 +95,23 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_pr ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void); ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(const zend_property_info *info, const char *operation); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(const zend_property_info *prop_info, const char *operation); ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg); ZEND_API ZEND_COLD void zend_verify_arg_error( - const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value); + const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, const zval *value); ZEND_API ZEND_COLD void zend_verify_return_error( - const zend_function *zf, zval *value); + const zend_function *zf, const zval *value); ZEND_API ZEND_COLD void zend_verify_never_error( const zend_function *zf); ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref); ZEND_API bool zend_check_user_type_slow( - zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, bool is_return_type); + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type); #if ZEND_DEBUG -ZEND_API bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call); -ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc); -ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret); +ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call); +ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(const zend_function *fbc); +ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *ret); #endif #define ZEND_REF_TYPE_SOURCES(ref) \ @@ -522,7 +522,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal #define ZEND_CLASS_HAS_READONLY_PROPS(ce) ((bool)(ce->ce_flags & ZEND_ACC_HAS_READONLY_PROPS)) -ZEND_API bool zend_verify_class_constant_type(zend_class_constant *c, const zend_string *name, zval *constant); +ZEND_API bool zend_verify_class_constant_type(const zend_class_constant *c, const zend_string *name, zval *constant); ZEND_COLD void zend_verify_class_constant_type_error(const zend_class_constant *c, const zend_string *name, const zval *constant); ZEND_API bool zend_verify_property_type(const zend_property_info *info, zval *property, bool strict); diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 53cd8533fd3e1..090b1049418d2 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -83,7 +83,7 @@ static void zend_type_list_copy_ctor( } zend_type *list_type; - ZEND_TYPE_LIST_FOREACH(new_list, list_type) { + ZEND_TYPE_LIST_FOREACH_MUTABLE(new_list, list_type) { zend_type_copy_ctor(list_type, use_arena, persistent); } ZEND_TYPE_LIST_FOREACH_END(); } @@ -362,7 +362,7 @@ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_en } static bool zend_type_permits_self( - zend_type type, const zend_class_entry *scope, zend_class_entry *self) { + const zend_type type, const zend_class_entry *scope, zend_class_entry *self) { if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) { return 1; } @@ -370,7 +370,7 @@ static bool zend_type_permits_self( /* Any types that may satisfy self must have already been loaded at this point * (as a parent or interface), so we never need to register delayed variance obligations * for this case. */ - zend_type *single_type; + const zend_type *single_type; ZEND_TYPE_FOREACH(type, single_type) { if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type)); @@ -428,12 +428,12 @@ static void track_class_dependency(zend_class_entry *ce, zend_string *class_name /* Check whether any type in the fe_type intersection type is a subtype of the proto class. */ static inheritance_status zend_is_intersection_subtype_of_class( - zend_class_entry *fe_scope, zend_type fe_type, + zend_class_entry *fe_scope, const zend_type fe_type, zend_class_entry *proto_scope, zend_string *proto_class_name, zend_class_entry *proto_ce) { ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(fe_type)); bool have_unresolved = false; - zend_type *single_type; + const zend_type *single_type; /* Traverse the list of child types and check that at least one is * a subtype of the parent type being checked */ @@ -473,7 +473,7 @@ static inheritance_status zend_is_intersection_subtype_of_class( /* Check whether a single class proto type is a subtype of a potentially complex fe_type. */ static inheritance_status zend_is_class_subtype_of_type( zend_class_entry *fe_scope, zend_string *fe_class_name, - zend_class_entry *proto_scope, zend_type proto_type) { + zend_class_entry *proto_scope, const zend_type proto_type) { zend_class_entry *fe_ce = NULL; bool have_unresolved = 0; @@ -513,7 +513,7 @@ static inheritance_status zend_is_class_subtype_of_type( } } - zend_type *single_type; + const zend_type *single_type; /* Traverse the list of parent types and check if the current child (FE) * class is the subtype of at least one of them (union) or all of them (intersection). */ @@ -584,15 +584,15 @@ static inheritance_status zend_is_class_subtype_of_type( return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } -static zend_string *get_class_from_type(const zend_class_entry *scope, zend_type single_type) { +static zend_string *get_class_from_type(const zend_class_entry *scope, const zend_type single_type) { if (ZEND_TYPE_HAS_NAME(single_type)) { return resolve_class_name(scope, ZEND_TYPE_NAME(single_type)); } return NULL; } -static void register_unresolved_classes(zend_class_entry *scope, zend_type type) { - zend_type *single_type; +static void register_unresolved_classes(zend_class_entry *scope, const zend_type type) { + const zend_type *single_type; ZEND_TYPE_FOREACH(type, single_type) { if (ZEND_TYPE_HAS_LIST(*single_type)) { register_unresolved_classes(scope, *single_type); @@ -606,11 +606,11 @@ static void register_unresolved_classes(zend_class_entry *scope, zend_type type) } static inheritance_status zend_is_intersection_subtype_of_type( - zend_class_entry *fe_scope, zend_type fe_type, - zend_class_entry *proto_scope, zend_type proto_type) + zend_class_entry *fe_scope, const zend_type fe_type, + zend_class_entry *proto_scope, const zend_type proto_type) { bool have_unresolved = false; - zend_type *single_type; + const zend_type *single_type; uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type); /* Currently, for object type any class name would be allowed here. @@ -672,8 +672,8 @@ static inheritance_status zend_is_intersection_subtype_of_type( } ZEND_API inheritance_status zend_perform_covariant_type_check( - zend_class_entry *fe_scope, zend_type fe_type, - zend_class_entry *proto_scope, zend_type proto_type) + zend_class_entry *fe_scope, const zend_type fe_type, + zend_class_entry *proto_scope, const zend_type proto_type) { ZEND_ASSERT(ZEND_TYPE_IS_SET(fe_type) && ZEND_TYPE_IS_SET(proto_type)); @@ -727,7 +727,7 @@ ZEND_API inheritance_status zend_perform_covariant_type_check( * We need to iterate over fe_type (U_i) first and the logic is independent of * whether proto_type is a union or intersection (only the inner check differs). */ early_exit_status = INHERITANCE_ERROR; - zend_type *single_type; + const zend_type *single_type; ZEND_TYPE_FOREACH(fe_type, single_type) { inheritance_status status; /* Union has an intersection type as it's member */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ce052024ae7a0..b25152ec1248b 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -112,7 +112,7 @@ ZEND_API void destroy_zend_function(zend_function *function) ZEND_API void zend_type_release(zend_type type, bool persistent) { if (ZEND_TYPE_HAS_LIST(type)) { zend_type *list_type; - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { + ZEND_TYPE_LIST_FOREACH_MUTABLE(ZEND_TYPE_LIST(type), list_type) { zend_type_release(*list_type, persistent); } ZEND_TYPE_LIST_FOREACH_END(); if (!ZEND_TYPE_USES_ARENA(type)) { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index f839cec3b3667..7676a1d42a5f4 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -209,8 +209,14 @@ typedef struct { /* This iterates over a zend_type_list. */ #define ZEND_TYPE_LIST_FOREACH(list, type_ptr) do { \ + const zend_type *_list = (list)->types; \ + const zend_type *_end = _list + (list)->num_types; \ + for (; _list < _end; _list++) { \ + type_ptr = _list; + +#define ZEND_TYPE_LIST_FOREACH_MUTABLE(list, type_ptr) do { \ zend_type *_list = (list)->types; \ - zend_type *_end = _list + (list)->num_types; \ + const zend_type *_end = _list + (list)->num_types; \ for (; _list < _end; _list++) { \ type_ptr = _list; @@ -221,7 +227,22 @@ typedef struct { /* This iterates over any zend_type. If it's a type list, all list elements will * be visited. If it's a single type, only the single type is visited. */ #define ZEND_TYPE_FOREACH(type, type_ptr) do { \ - zend_type *_cur, *_end; \ + const zend_type *_cur, *_end; \ + if (ZEND_TYPE_HAS_LIST(type)) { \ + zend_type_list *_list = ZEND_TYPE_LIST(type); \ + _cur = _list->types; \ + _end = _cur + _list->num_types; \ + } else { \ + _cur = &(type); \ + _end = _cur + 1; \ + } \ + do { \ + type_ptr = _cur; + + +#define ZEND_TYPE_FOREACH_MUTABLE(type, type_ptr) do { \ + zend_type *_cur; \ + const zend_type *_end; \ if (ZEND_TYPE_HAS_LIST(type)) { \ zend_type_list *_list = ZEND_TYPE_LIST(type); \ _cur = _list->types; \ diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 8caa0cbd4398e..704846c4a860f 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -626,7 +626,7 @@ static inline void accel_copy_permanent_list_types( zend_new_interned_string_func_t new_interned_string, zend_type type) { zend_type *single_type; - ZEND_TYPE_FOREACH(type, single_type) { + ZEND_TYPE_FOREACH_MUTABLE(type, single_type) { if (ZEND_TYPE_HAS_LIST(*single_type)) { ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(*single_type)); accel_copy_permanent_list_types(new_interned_string, *single_type); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index a2346a56d458e..d2b714d937dac 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -468,7 +468,7 @@ static void zend_file_cache_serialize_type( UNSERIALIZE_PTR(list); zend_type *list_type; - ZEND_TYPE_LIST_FOREACH(list, list_type) { + ZEND_TYPE_LIST_FOREACH_MUTABLE(list, list_type) { zend_file_cache_serialize_type(list_type, script, info, buf); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { @@ -1348,7 +1348,7 @@ static void zend_file_cache_unserialize_type( ZEND_TYPE_SET_PTR(*type, list); zend_type *list_type; - ZEND_TYPE_LIST_FOREACH(list, list_type) { + ZEND_TYPE_LIST_FOREACH_MUTABLE(list, list_type) { zend_file_cache_unserialize_type(list_type, scope, script, buf); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(*type)) { diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 3d45c63a98781..a384cdd2b9a06 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -367,7 +367,7 @@ static void zend_persist_type(zend_type *type) { } zend_type *single_type; - ZEND_TYPE_FOREACH(*type, single_type) { + ZEND_TYPE_FOREACH_MUTABLE(*type, single_type) { if (ZEND_TYPE_HAS_LIST(*single_type)) { zend_persist_type(single_type); continue; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index bb4f9c7170f28..42a6cf76d62da 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -197,7 +197,7 @@ static void zend_persist_type_calc(zend_type *type) } zend_type *single_type; - ZEND_TYPE_FOREACH(*type, single_type) { + ZEND_TYPE_FOREACH_MUTABLE(*type, single_type) { if (ZEND_TYPE_HAS_LIST(*single_type)) { zend_persist_type_calc(single_type); continue; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index b53b7b97c9bc9..bff617cfb61de 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -3170,7 +3170,7 @@ ZEND_METHOD(ReflectionUnionType, getTypes) array_init(return_value); if (ZEND_TYPE_HAS_LIST(param->type)) { - zend_type *list_type; + const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), list_type) { append_type(return_value, *list_type); } ZEND_TYPE_LIST_FOREACH_END(); @@ -3221,7 +3221,7 @@ ZEND_METHOD(ReflectionIntersectionType, getTypes) { reflection_object *intern; type_reference *param; - zend_type *list_type; + const zend_type *list_type; ZEND_PARSE_PARAMETERS_NONE(); GET_REFLECTION_OBJECT_PTR(param); From 61f704f26990326a86d925e1374093e9b2e2bed2 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 17 Mar 2025 14:12:11 +0000 Subject: [PATCH 297/503] ext/libxml: Fixed custom external entity loader returning an invalid resource leading to a confusing TypeError message Closes GH-18096 --- NEWS | 4 ++++ ext/libxml/libxml.c | 19 ++++++++++++------- ...nal_entity_loader_error_callback_name.phpt | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 774058d253783..71430bc20b0ff 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS . Fixed GH-18243 imagettftext() overflow/underflow on font size value. (David Carlier) +- libxml: + . Fixed custom external entity loader returning an invalid resource leading + to a confusing TypeError message. (Girgias) + - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. (nielsdos) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 18ca51e36a052..5c903d2c9a228 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -793,13 +793,18 @@ static xmlParserInputPtr _php_libxml_external_entity_loader(const char *URL, is_string: resource = Z_STRVAL(retval); } else if (Z_TYPE(retval) == IS_RESOURCE) { - php_stream *stream; - php_stream_from_zval_no_verify(stream, &retval); - if (stream == NULL) { - php_libxml_ctx_error(context, - "The user entity loader callback '%s' has returned a " - "resource, but it is not a stream", - ZSTR_VAL(LIBXML(entity_loader_callback).function_handler->common.function_name)); + php_stream *stream = (php_stream*)zend_fetch_resource2_ex(&retval, NULL, php_file_le_stream(), php_file_le_pstream()); + if (UNEXPECTED(stream == NULL)) { + zval callable; + zend_get_callable_zval_from_fcc(&LIBXML(entity_loader_callback), &callable); + zend_string *callable_name = zend_get_callable_name(&callable); + zend_string *func_name = get_active_function_or_method_name(); + zend_type_error( + "%s(): The user entity loader callback \"%s\" has returned a resource, but it is not a stream", + ZSTR_VAL(func_name), ZSTR_VAL(callable_name)); + zend_string_release(func_name); + zend_string_release(callable_name); + zval_ptr_dtor(&callable); } else { /* TODO: allow storing the encoding in the stream context? */ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; diff --git a/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt b/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt index 1bdbbfb5b817e..2122785ef5b9b 100644 --- a/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt +++ b/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt @@ -40,4 +40,4 @@ $file = __DIR__ . '/db.dba'; unlink($file); ?> --EXPECT-- -string(73) "DOMDocument::validate(): supplied resource is not a valid stream resource" +string(122) "DOMDocument::validate(): The user entity loader callback "Handler::handle" has returned a resource, but it is not a stream" From bd4333447e0dfbac097f60e0ed675277219dd743 Mon Sep 17 00:00:00 2001 From: acc987 <39603492+acc987@users.noreply.github.com> Date: Thu, 3 Apr 2025 18:16:19 +0200 Subject: [PATCH 298/503] Add OffsetTime* Exif tags Closes GH-18237. --- NEWS | 3 ++ UPGRADING | 3 ++ ext/exif/exif.c | 6 ++++ ext/exif/tests/exif028.phpt | 59 ++++++++++++++++++++++++++++++++++++ ext/exif/tests/image028.jpg | Bin 0 -> 527 bytes 5 files changed, 71 insertions(+) create mode 100644 ext/exif/tests/exif028.phpt create mode 100644 ext/exif/tests/image028.jpg diff --git a/NEWS b/NEWS index 65cebd217e130..c37cec11fda0f 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,9 @@ PHP NEWS . Added enchant_dict_remove_from_session(). (nielsdos) . Added enchant_dict_remove(). (nielsdos) +- EXIF: + . Add OffsetTime* Exif tags. (acc987) + - Fileinfo: . Upgrade to file 5.46. (nielsdos) diff --git a/UPGRADING b/UPGRADING index 26ed02c9af9a0..6cc0cc537df2d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -151,6 +151,9 @@ PHP 8.5 UPGRADE NOTES - DOM: . Added Dom\Element::$outerHTML. +- EXIF: + . Add OffsetTime* Exif tags. + - XSL: . The $namespace argument of XSLTProcessor::getParameter(), XSLTProcessor::setParameter() and XSLTProcessor::removeParameter() diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 0f63c76e2323f..9169861728869 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -420,6 +420,9 @@ static char *exif_get_tagformat(int format) #define TAG_EXIFVERSION 0x9000 #define TAG_DATE_TIME_ORIGINAL 0x9003 #define TAG_DATE_TIME_DIGITIZED 0x9004 +#define TAG_OFFSET_TIME 0x9010 +#define TAG_OFFSET_TIME_ORIGINAL 0x9011 +#define TAG_OFFSET_TIME_DIGITIZED 0x9012 #define TAG_COMPONENT_CONFIG 0x9101 #define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102 #define TAG_SHUTTERSPEED 0x9201 @@ -692,6 +695,9 @@ static tag_info_array tag_table_IFD = { { 0x9000, "ExifVersion"}, { 0x9003, "DateTimeOriginal"}, { 0x9004, "DateTimeDigitized"}, + { 0x9010, "OffsetTime"}, + { 0x9011, "OffsetTimeOriginal"}, + { 0x9012, "OffsetTimeDigitized"}, { 0x9101, "ComponentsConfiguration"}, { 0x9102, "CompressedBitsPerPixel"}, { 0x9201, "ShutterSpeedValue"}, diff --git a/ext/exif/tests/exif028.phpt b/ext/exif/tests/exif028.phpt new file mode 100644 index 0000000000000..5ca06616ba679 --- /dev/null +++ b/ext/exif/tests/exif028.phpt @@ -0,0 +1,59 @@ +--TEST-- +Check for exif_read_data, JPEG with IFD data containg OffsetTime, OffsetTimeOriginal, and OffsetTimeDigitized tags in Motorola byte-order. +--EXTENSIONS-- +exif +--INI-- +output_handler= +zlib.output_compression=0 +--FILE-- + +--EXPECTF-- +array(17) { + ["FileName"]=> + string(12) "image028.jpg" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(%d) + ["FileType"]=> + int(2) + ["MimeType"]=> + string(10) "image/jpeg" + ["SectionsFound"]=> + string(13) "ANY_TAG, IFD0" + ["COMPUTED"]=> + array(5) { + ["html"]=> + string(20) "width="1" height="1"" + ["Height"]=> + int(1) + ["Width"]=> + int(1) + ["IsColor"]=> + int(1) + ["ByteOrderMotorola"]=> + int(1) + } + ["XResolution"]=> + string(5) "300/1" + ["YResolution"]=> + string(5) "300/1" + ["ResolutionUnit"]=> + int(2) + ["DateTime"]=> + string(19) "2025:04:03 00:02:00" + ["YCbCrPositioning"]=> + int(1) + ["DateTimeOriginal"]=> + string(19) "2025:04:03 00:00:00" + ["DateTimeDigitized"]=> + string(19) "2025:04:03 00:01:00" + ["OffsetTime"]=> + string(6) "-02:00" + ["OffsetTimeOriginal"]=> + string(6) "+00:00" + ["OffsetTimeDigitized"]=> + string(6) "-01:00" +} diff --git a/ext/exif/tests/image028.jpg b/ext/exif/tests/image028.jpg new file mode 100644 index 0000000000000000000000000000000000000000..57110cec8f768dcd6ea9970a20f37f783c7a9d74 GIT binary patch literal 527 zcmbV|F>V4e5JmsspdduCCaIvIM6gK1LYi$T5G#SiHITRg9bL-ERSuCupcFYlDza%H zN8kcxWH`5YYp6;!E#vM7>#rDo7? z)P^Z|Nj4M6h-b<7($kqsg)@PFxQC!OE-Lh+od0$<=-kzV{*yfkeU Date: Mon, 7 Apr 2025 19:50:48 +0200 Subject: [PATCH 299/503] Remove cache slot from ZEND_VERIFY_TYPE and arg RECV opcodes (#18258) --- UPGRADING.INTERNALS | 2 + Zend/Optimizer/compact_literals.c | 64 ------------------------ Zend/zend_compile.c | 35 ------------- Zend/zend_execute.c | 80 ++++++++++-------------------- Zend/zend_execute.h | 2 +- Zend/zend_vm_def.h | 21 ++++---- Zend/zend_vm_execute.h | 23 ++++----- Zend/zend_vm_opcodes.c | 8 +-- ext/opcache/jit/zend_jit_helpers.c | 7 ++- ext/opcache/jit/zend_jit_ir.c | 5 +- 10 files changed, 57 insertions(+), 190 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index eb5ccd7bd0bd0..56c7535158460 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -25,6 +25,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES char* instead of zend_string*-based smart strings. . Added php_build_provider() to retrieve the value of PHP_BUILD_PROVIDER at runtime. + . Removed the cache_slot argument of zend_check_user_type_slow() because + now it only relies on the CE cache. ======================== 2. Build system changes diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index 202cb7c2d6114..d0aaccec7ce2c 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -43,50 +43,6 @@ typedef struct _literal_info { info[n].num_related = (related); \ } while (0) -static size_t type_num_classes(const zend_op_array *op_array, uint32_t arg_num) -{ - zend_arg_info *arg_info; - if (arg_num > 0) { - if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) { - return 0; - } - if (EXPECTED(arg_num <= op_array->num_args)) { - arg_info = &op_array->arg_info[arg_num-1]; - } else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) { - arg_info = &op_array->arg_info[op_array->num_args]; - } else { - return 0; - } - } else { - arg_info = op_array->arg_info - 1; - } - - if (ZEND_TYPE_IS_COMPLEX(arg_info->type)) { - if (ZEND_TYPE_HAS_LIST(arg_info->type)) { - /* Intersection types cannot have nested list types */ - if (ZEND_TYPE_IS_INTERSECTION(arg_info->type)) { - return ZEND_TYPE_LIST(arg_info->type)->num_types; - } - ZEND_ASSERT(ZEND_TYPE_IS_UNION(arg_info->type)); - size_t count = 0; - const zend_type *list_type; - - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) { - if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { - count += ZEND_TYPE_LIST(*list_type)->num_types; - } else { - ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); - count += 1; - } - } ZEND_TYPE_LIST_FOREACH_END(); - return count; - } - return 1; - } - - return 0; -} - static uint32_t add_static_slot(HashTable *hash, zend_op_array *op_array, uint32_t op1, @@ -504,26 +460,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx opline->op2.constant = map[opline->op2.constant]; } switch (opline->opcode) { - case ZEND_RECV_INIT: - case ZEND_RECV: - case ZEND_RECV_VARIADIC: - { - size_t num_classes = type_num_classes(op_array, opline->op1.num); - if (num_classes) { - opline->extended_value = cache_size; - cache_size += num_classes * sizeof(void *); - } - break; - } - case ZEND_VERIFY_RETURN_TYPE: - { - size_t num_classes = type_num_classes(op_array, 0); - if (num_classes) { - opline->op2.num = cache_size; - cache_size += num_classes * sizeof(void *); - } - break; - } case ZEND_ASSIGN_STATIC_PROP_OP: if (opline->op1_type == IS_CONST) { // op1 static property diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3fa4c3959cb43..2ad3f6b323d8f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2620,33 +2620,6 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ } /* }}} */ -/* Remember to update type_num_classes() in compact_literals.c when changing this function */ -static size_t zend_type_get_num_classes(const zend_type type) { - if (!ZEND_TYPE_IS_COMPLEX(type)) { - return 0; - } - if (ZEND_TYPE_HAS_LIST(type)) { - /* Intersection types cannot have nested list types */ - if (ZEND_TYPE_IS_INTERSECTION(type)) { - return ZEND_TYPE_LIST(type)->num_types; - } - ZEND_ASSERT(ZEND_TYPE_IS_UNION(type)); - size_t count = 0; - const zend_type *list_type; - - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { - if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { - count += ZEND_TYPE_LIST(*list_type)->num_types; - } else { - ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); - count += 1; - } - } ZEND_TYPE_LIST_FOREACH_END(); - return count; - } - return 1; -} - static void zend_emit_return_type_check( znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */ { @@ -2708,8 +2681,6 @@ static void zend_emit_return_type_check( opline->result_type = expr->op_type = IS_TMP_VAR; opline->result.var = expr->u.op.var = get_temporary_variable(); } - - opline->op2.num = zend_alloc_cache_slots(zend_type_get_num_classes(return_info->type)); } } /* }}} */ @@ -7754,12 +7725,6 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 SET_NODE(opline->result, &var_node); opline->op1.num = i + 1; - if (type_ast) { - /* Allocate cache slot to speed-up run-time class resolution */ - opline->extended_value = - zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type)); - } - uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0) | (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0); ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 786cd60ef1401..89fbcf2cbd781 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1099,23 +1099,9 @@ static zend_always_inline bool zend_value_instanceof_static(const zval *zv) { return instanceof_function(Z_OBJCE_P(zv), called_scope); } -/* The cache_slot may only be NULL in debug builds, where arginfo verification of - * internal functions is enabled. Avoid unnecessary checks in release builds. */ -#if ZEND_DEBUG -# define HAVE_CACHE_SLOT (cache_slot != NULL) -#else -# define HAVE_CACHE_SLOT 1 -#endif - -#define PROGRESS_CACHE_SLOT() if (HAVE_CACHE_SLOT) {cache_slot++;} - -static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot( - void **cache_slot, const zend_type *type) +static zend_always_inline zend_class_entry *zend_fetch_ce_from_type( + const zend_type *type) { - if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) { - return (zend_class_entry *) *cache_slot; - } - zend_string *name = ZEND_TYPE_NAME(*type); zend_class_entry *ce; if (ZSTR_HAS_CE_CACHE(name)) { @@ -1134,68 +1120,54 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot( return NULL; } } - if (HAVE_CACHE_SLOT) { - *cache_slot = (void *) ce; - } return ce; } -static bool zend_check_intersection_type_from_cache_slot( +static bool zend_check_intersection_type_from_list( const zend_type_list *intersection_type_list, - const zend_class_entry *arg_ce, - void ***cache_slot_ptr) + zend_class_entry *arg_ce) { - void **cache_slot = *cache_slot_ptr; + zend_class_entry *ce; const zend_type *list_type; - bool status = true; ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) { - /* Only check classes if the type might be valid */ - if (status) { - zend_class_entry *ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); - /* If type is not an instance of one of the types taking part in the - * intersection it cannot be a valid instance of the whole intersection type. */ - if (!ce || !instanceof_function(arg_ce, ce)) { - status = false; - } + ce = zend_fetch_ce_from_type(list_type); + /* If type is not an instance of one of the types taking part in the + * intersection it cannot be a valid instance of the whole intersection type. */ + if (!ce || !instanceof_function(arg_ce, ce)) { + return false; } - PROGRESS_CACHE_SLOT(); } ZEND_TYPE_LIST_FOREACH_END(); - if (HAVE_CACHE_SLOT) { - *cache_slot_ptr = cache_slot; - } - return status; + return true; } static zend_always_inline bool zend_check_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, + const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type, bool is_internal) { if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { zend_class_entry *ce; if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) { if (ZEND_TYPE_IS_INTERSECTION(*type)) { - return zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg), &cache_slot); + return zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg)); } else { const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { - if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), &cache_slot)) { + if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) { return true; } - /* The cache_slot is progressed in zend_check_intersection_type_from_cache_slot() */ } else { ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); - ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); + ce = zend_fetch_ce_from_type(list_type); /* Instance of a single type part of a union is sufficient to pass the type check */ if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { return true; } - PROGRESS_CACHE_SLOT(); } } ZEND_TYPE_LIST_FOREACH_END(); } } else { - ce = zend_fetch_ce_from_cache_slot(cache_slot, type); + ce = zend_fetch_ce_from_type(type); /* If we have a CE we check if it satisfies the type constraint, * otherwise it will check if a standard type satisfies it. */ if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { @@ -1232,7 +1204,7 @@ static zend_always_inline bool zend_check_type_slow( } static zend_always_inline bool zend_check_type( - const zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope, + const zend_type *type, zval *arg, zend_class_entry *scope, bool is_return_type, bool is_internal) { const zend_reference *ref = NULL; @@ -1247,17 +1219,17 @@ static zend_always_inline bool zend_check_type( return 1; } - return zend_check_type_slow(type, arg, ref, cache_slot, is_return_type, is_internal); + return zend_check_type_slow(type, arg, ref, is_return_type, is_internal); } ZEND_API bool zend_check_user_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type) + const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type) { return zend_check_type_slow( - type, arg, ref, cache_slot, is_return_type, /* is_internal */ false); + type, arg, ref, is_return_type, /* is_internal */ false); } -static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) +static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg) { const zend_arg_info *cur_arg_info; @@ -1265,7 +1237,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf cur_arg_info = &zf->common.arg_info[arg_num-1]; if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, cur_arg_info, arg_num, arg); return 0; } @@ -1274,10 +1246,10 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf } static zend_always_inline bool zend_verify_variadic_arg_type( - const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) + const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); - if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, arg_info, arg_num, arg); return 0; } @@ -1302,7 +1274,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ } if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, 0, /* is_internal */ 1))) { return 0; } arg++; @@ -1508,7 +1480,7 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re return 1; } - if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) { + if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, 1, /* is_internal */ 1))) { zend_verify_internal_return_error(zf, ret); return 0; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 75c2d07e5e5cb..97ef66879db91 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -106,7 +106,7 @@ ZEND_API ZEND_COLD void zend_verify_never_error( const zend_function *zf); ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref); ZEND_API bool zend_check_user_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type); + const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type); #if ZEND_DEBUG ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 162b7e84cefbe..9317d1ff592f5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4423,7 +4423,7 @@ ZEND_VM_C_LABEL(fcall_end): ZEND_VM_CONTINUE(); } -ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED|CACHE_SLOT) +ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) { if (OP1_TYPE == IS_UNUSED) { SAVE_OPLINE(); @@ -4465,7 +4465,6 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -4482,7 +4481,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -5671,14 +5670,14 @@ ZEND_VM_HELPER(zend_verify_recv_arg_type_helper, ANY, ANY, zval *op_1) USE_OPLINE SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) { HANDLE_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT) +ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5697,7 +5696,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM, CACHE_SLOT) +ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5709,7 +5708,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NO ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) +ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST) { USE_OPLINE uint32_t arg_num; @@ -5749,7 +5748,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) ZEND_VM_C_LABEL(recv_init_check_type): if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) { HANDLE_EXCEPTION(); } } @@ -5759,7 +5758,7 @@ ZEND_VM_C_LABEL(recv_init_check_type): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) +ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5782,7 +5781,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) if (ZEND_TYPE_IS_SET(arg_info->type)) { ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { ZEND_HASH_FILL_FINISH(); HANDLE_EXCEPTION(); } @@ -5810,7 +5809,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { HANDLE_EXCEPTION(); } Z_TRY_ADDREF_P(param); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 902e254ff2424..f7bec6f7198c8 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2757,7 +2757,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_ USE_OPLINE SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) { HANDLE_EXCEPTION(); } @@ -4190,7 +4190,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON recv_init_check_type: if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) { HANDLE_EXCEPTION(); } } @@ -4295,7 +4295,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND if (ZEND_TYPE_IS_SET(arg_info->type)) { ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { ZEND_HASH_FILL_FINISH(); HANDLE_EXCEPTION(); } @@ -4323,7 +4323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { HANDLE_EXCEPTION(); } Z_TRY_ADDREF_P(param); @@ -10869,7 +10869,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -10886,7 +10885,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -21606,7 +21605,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -21623,7 +21621,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -30086,7 +30084,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -30103,7 +30100,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -37880,7 +37877,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -37897,7 +37893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -50681,7 +50677,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } zend_reference *ref = NULL; - void *cache_slot = CACHE_ADDR(opline->op2.num); if (UNEXPECTED(retval_ref != retval_ptr)) { if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { ref = Z_REF_P(retval_ref); @@ -50698,7 +50693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 202dfd3f734f3..d7d4d9e770b5b 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -299,8 +299,8 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000000, 0x01040310, 0x00000003, - 0x00040110, - 0x00040310, + 0x00000110, + 0x00000310, 0x00001307, 0x00001301, 0x00001301, @@ -360,7 +360,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000007, 0x00040003, 0x09000007, - 0x0000a103, + 0x00000103, 0x00002003, 0x03000001, 0x00000005, @@ -400,7 +400,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000003, 0x00000020, 0x00003000, - 0x00040110, + 0x00000110, 0x00000000, 0x00000007, 0x00000105, diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 177feea3afa6e..b20afffa47df0 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1900,9 +1900,8 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg { zend_execute_data *execute_data = EG(current_execute_data); const zend_op *opline = EX(opline); - void **cache_slot = CACHE_ADDR(opline->extended_value); bool ret = zend_check_user_type_slow( - &arg_info->type, arg, /* ref */ NULL, cache_slot, /* is_return_type */ false); + &arg_info->type, arg, /* ref */ NULL, /* is_return_type */ false); if (UNEXPECTED(!ret)) { zend_verify_arg_error(EX(func), arg_info, opline->op1.num, arg); return 0; @@ -1910,7 +1909,7 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg return ret; } -static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_array *op_array, zend_arg_info *arg_info, void **cache_slot) +static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_array *op_array, zend_arg_info *arg_info) { if (Z_TYPE_P(arg) == IS_NULL) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); @@ -1919,7 +1918,7 @@ static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_a } } if (UNEXPECTED(!zend_check_user_type_slow( - &arg_info->type, arg, /* ref */ NULL, cache_slot, /* is_return_type */ true))) { + &arg_info->type, arg, /* ref */ NULL, /* is_return_type */ true))) { zend_verify_return_error((zend_function*)op_array, arg); } } diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 4d006c19d34e9..09bfadd9f1fb0 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -11031,11 +11031,10 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline ref = zend_jit_zval_check_undef(jit, ref, opline->op1.var, NULL, 1); } - ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_verify_return_slow), + ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_verify_return_slow), ref, ir_LOAD_A(jit_EX(func)), - ir_CONST_ADDR(arg_info), - ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), opline->op2.num)); + ir_CONST_ADDR(arg_info)); zend_jit_check_exception(jit); From f14697416e98cb2307d9b0839262e5526e189ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 8 Apr 2025 14:23:03 +0200 Subject: [PATCH 300/503] ext/standard: Remove `#[\NoDiscard]` from `flock()` (#18255) Co-authored-by: Volker Dusch --- Zend/tests/attributes/nodiscard/005.phpt | 8 +--- Zend/tests/attributes/nodiscard/007.phpt | 10 ++-- Zend/tests/attributes/nodiscard/010.phpt | 12 +++++ ext/opcache/tests/nodiscard_001.phpt | 59 +++++++++--------------- ext/standard/basic_functions.stub.php | 1 - ext/standard/basic_functions_arginfo.h | 13 +----- ext/zend_test/test.c | 7 +++ ext/zend_test/test.stub.php | 2 + ext/zend_test/test_arginfo.h | 25 ++++++++-- 9 files changed, 71 insertions(+), 66 deletions(-) create mode 100644 Zend/tests/attributes/nodiscard/010.phpt diff --git a/Zend/tests/attributes/nodiscard/005.phpt b/Zend/tests/attributes/nodiscard/005.phpt index ec8f33e5299d6..9ef1566372892 100644 --- a/Zend/tests/attributes/nodiscard/005.phpt +++ b/Zend/tests/attributes/nodiscard/005.phpt @@ -1,17 +1,11 @@ --TEST-- -#[\NoDiscard]: Native function and method. +#[\NoDiscard]: Native method. --FILE-- setTimestamp(0); ?> --EXPECTF-- -Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d - Warning: The return value of method DateTimeImmutable::setTimestamp() should either be used or intentionally ignored by casting it as (void), as DateTimeImmutable::setTimestamp() does not modify the object itself in %s on line %d diff --git a/Zend/tests/attributes/nodiscard/007.phpt b/Zend/tests/attributes/nodiscard/007.phpt index 84dff0c8e44f6..1b72de8c22a06 100644 --- a/Zend/tests/attributes/nodiscard/007.phpt +++ b/Zend/tests/attributes/nodiscard/007.phpt @@ -7,15 +7,11 @@ zend_test.observer.execute_internal=1 --FILE-- --EXPECTF-- - -Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d - - +Warning: The return value of function zend_test_nodiscard() should either be used or intentionally ignored by casting it as (void), custom message in %s on line %d + diff --git a/Zend/tests/attributes/nodiscard/010.phpt b/Zend/tests/attributes/nodiscard/010.phpt new file mode 100644 index 0000000000000..5534fc3404da9 --- /dev/null +++ b/Zend/tests/attributes/nodiscard/010.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[\NoDiscard]: Native function. +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Warning: The return value of function zend_test_nodiscard() should either be used or intentionally ignored by casting it as (void), custom message in %s on line %d diff --git a/ext/opcache/tests/nodiscard_001.phpt b/ext/opcache/tests/nodiscard_001.phpt index f4f7b8488e98a..7e232f8f44e41 100644 --- a/ext/opcache/tests/nodiscard_001.phpt +++ b/ext/opcache/tests/nodiscard_001.phpt @@ -7,14 +7,13 @@ opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 --EXTENSIONS-- opcache +zend_test --FILE-- --EXPECTF-- $_main: - ; (lines=29, args=0, vars=3, tmps=%d) + ; (lines=17, args=0, vars=2, tmps=%d) ; (after optimizer) ; %s -0000 INIT_FCALL 0 %d string("tmpfile") -0001 V3 = DO_ICALL -0002 ASSIGN CV0($f) V3 -0003 INIT_FCALL 2 %d string("flock") -0004 SEND_VAR CV0($f) 1 -0005 SEND_VAL int(5) 2 -0006 DO_FCALL_BY_NAME -0007 INIT_FCALL 2 %d string("flock") -0008 SEND_VAR CV0($f) 1 -0009 SEND_VAL int(5) 2 -0010 V3 = DO_ICALL -0011 FREE V3 -0012 INIT_FCALL 2 %d string("flock") -0013 SEND_VAR CV0($f) 1 -0014 SEND_VAL int(5) 2 -0015 V3 = DO_ICALL -0016 ASSIGN CV1($success) V3 -0017 INIT_FCALL 1 %d string("fclose") -0018 SEND_VAR CV0($f) 1 -0019 DO_ICALL -0020 INIT_FCALL 0 %d string("test") -0021 DO_FCALL_BY_NAME -0022 INIT_FCALL 0 %d string("test") -0023 V3 = DO_UCALL -0024 FREE V3 -0025 INIT_FCALL 0 %d string("test") -0026 V3 = DO_UCALL -0027 ASSIGN CV2($obj) V3 -0028 RETURN int(1) +0000 INIT_FCALL 0 %d string("zend_test_nodiscard") +0001 DO_FCALL_BY_NAME +0002 INIT_FCALL 0 %d string("zend_test_nodiscard") +0003 V2 = DO_ICALL +0004 FREE V2 +0005 INIT_FCALL 0 %d string("zend_test_nodiscard") +0006 V2 = DO_ICALL +0007 ASSIGN CV0($success) V2 +0008 INIT_FCALL 0 %d string("test") +0009 DO_FCALL_BY_NAME +0010 INIT_FCALL 0 %d string("test") +0011 V2 = DO_UCALL +0012 FREE V2 +0013 INIT_FCALL 0 %d string("test") +0014 V2 = DO_UCALL +0015 ASSIGN CV1($obj) V2 +0016 RETURN int(1) test: ; (lines=3, args=0, vars=0, tmps=%d) @@ -71,6 +58,6 @@ test: LIVE RANGES: 0: 0001 - 0002 (new) -Warning: The return value of function flock() should either be used or intentionally ignored by casting it as (void), as locking the stream might have failed in %s on line %d +Warning: The return value of function zend_test_nodiscard() should either be used or intentionally ignored by casting it as (void), custom message in %s on line %d Warning: The return value of function test() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index b6533d8dc20e8..e7f4ff8844714 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2732,7 +2732,6 @@ function proc_nice(int $priority): bool {} * @param resource $stream * @param int $would_block */ -#[\NoDiscard(message: "as locking the stream might have failed")] function flock($stream, int $operation, &$would_block = null): bool {} /** diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index d35377c900735..3d92288643159 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 824ccb41163307bd0fad452b705a8222b6f42d09 */ + * Stub hash: 85677dc3476d25b7820fd3a26fe39f2e9378b6e7 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -3205,7 +3205,7 @@ static const zend_function_entry ext_functions[] = { #if defined(HAVE_NICE) ZEND_FE(proc_nice, arginfo_proc_nice) #endif - ZEND_RAW_FENTRY("flock", zif_flock, arginfo_flock, ZEND_ACC_NODISCARD, NULL, NULL) + ZEND_FE(flock, arginfo_flock) ZEND_FE(get_meta_tags, arginfo_get_meta_tags) ZEND_FE(pclose, arginfo_pclose) ZEND_FE(popen, arginfo_popen) @@ -4039,15 +4039,6 @@ static void register_basic_functions_symbols(int module_number) ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_decode_0->args[1].value, &attribute_Deprecated_func_utf8_decode_0_arg1); attribute_Deprecated_func_utf8_decode_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); - zend_string *attribute_name_NoDiscard_func_flock_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); - zend_attribute *attribute_NoDiscard_func_flock_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "flock", sizeof("flock") - 1), attribute_name_NoDiscard_func_flock_0, 1); - zend_string_release(attribute_name_NoDiscard_func_flock_0); - zval attribute_NoDiscard_func_flock_0_arg0; - zend_string *attribute_NoDiscard_func_flock_0_arg0_str = zend_string_init("as locking the stream might have failed", strlen("as locking the stream might have failed"), 1); - ZVAL_STR(&attribute_NoDiscard_func_flock_0_arg0, attribute_NoDiscard_func_flock_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_flock_0->args[0].value, &attribute_NoDiscard_func_flock_0_arg0); - attribute_NoDiscard_func_flock_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); - zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_hash", sizeof("password_hash") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_verify", sizeof("password_verify") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index b9190f6753052..ba18639aead82 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -124,6 +124,13 @@ static ZEND_FUNCTION(zend_test_deprecated_attr) ZEND_PARSE_PARAMETERS_NONE(); } +static ZEND_FUNCTION(zend_test_nodiscard) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_LONG(1); +} + static ZEND_FUNCTION(zend_test_deprecated_nodiscard) { ZEND_PARSE_PARAMETERS_NONE(); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 921dadd00ce15..10272c51cad49 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -218,6 +218,8 @@ function zend_test_deprecated(mixed $arg = null): void {} #[\Deprecated(message: "custom message")] function zend_test_deprecated_attr(): void {} + #[\NoDiscard(message: "custom message")] + function zend_test_nodiscard(): int {} #[\Deprecated(message: "custom message")] #[\NoDiscard(message: "custom message 2")] diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 391f2fc500b02..62b57223dac2a 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: eebe535d0295f707201ff751e38a5ad3837dbbd2 */ + * Stub hash: bedc3883fbfe2491c95375beb13140e7fcfd83a5 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -22,9 +22,11 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_deprecated_attr arginfo_zend_test_void_return -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_deprecated_nodiscard, 0, 0, IS_LONG, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_nodiscard, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() +#define arginfo_zend_test_deprecated_nodiscard arginfo_zend_test_nodiscard + #define arginfo_zend_test_aliased arginfo_zend_test_void_return #define arginfo_zend_test_deprecated_aliased arginfo_zend_test_void_return @@ -131,7 +133,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_is_string_marked_as_va ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_zend_get_map_ptr_last arginfo_zend_test_deprecated_nodiscard +#define arginfo_zend_get_map_ptr_last arginfo_zend_test_nodiscard ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_crash, 0, 0, IS_VOID, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, message, IS_STRING, 1, "null") @@ -189,7 +191,7 @@ ZEND_END_ARG_INFO() #define arginfo_ZendTestNS2_ZendSubNS_namespaced_deprecated_aliased_func arginfo_zend_test_void_return -#define arginfo_class__ZendTestClass_is_object arginfo_zend_test_deprecated_nodiscard +#define arginfo_class__ZendTestClass_is_object arginfo_zend_test_nodiscard #define arginfo_class__ZendTestClass___toString arginfo_zend_get_current_func_name @@ -264,6 +266,7 @@ static ZEND_FUNCTION(zend_test_void_return); static ZEND_FUNCTION(zend_test_compile_string); static ZEND_FUNCTION(zend_test_deprecated); static ZEND_FUNCTION(zend_test_deprecated_attr); +static ZEND_FUNCTION(zend_test_nodiscard); static ZEND_FUNCTION(zend_test_deprecated_nodiscard); static ZEND_FUNCTION(zend_create_unterminated_string); static ZEND_FUNCTION(zend_terminate_string); @@ -361,6 +364,11 @@ static const zend_function_entry ext_functions[] = { #else ZEND_RAW_FENTRY("zend_test_deprecated_attr", zif_zend_test_deprecated_attr, arginfo_zend_test_deprecated_attr, ZEND_ACC_DEPRECATED) #endif +#if (PHP_VERSION_ID >= 80400) + ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, ZEND_ACC_NODISCARD, NULL, NULL) +#else + ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, ZEND_ACC_NODISCARD) +#endif #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD, NULL, NULL) #else @@ -572,6 +580,15 @@ static void register_test_symbols(int module_number) ZVAL_COPY_VALUE(&attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].value, &attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0); attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_string *attribute_name_NoDiscard_func_zend_test_nodiscard_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + zend_attribute *attribute_NoDiscard_func_zend_test_nodiscard_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_nodiscard", sizeof("zend_test_nodiscard") - 1), attribute_name_NoDiscard_func_zend_test_nodiscard_0, 1); + zend_string_release(attribute_name_NoDiscard_func_zend_test_nodiscard_0); + zval attribute_NoDiscard_func_zend_test_nodiscard_0_arg0; + zend_string *attribute_NoDiscard_func_zend_test_nodiscard_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); + ZVAL_STR(&attribute_NoDiscard_func_zend_test_nodiscard_0_arg0, attribute_NoDiscard_func_zend_test_nodiscard_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_NoDiscard_func_zend_test_nodiscard_0->args[0].value, &attribute_NoDiscard_func_zend_test_nodiscard_0_arg0); + attribute_NoDiscard_func_zend_test_nodiscard_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_string *attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); zend_attribute *attribute_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_nodiscard", sizeof("zend_test_deprecated_nodiscard") - 1), attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0, 1); zend_string_release(attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0); From 2194ad81f4d816ad32ad03bcd471fb0c2469c5f8 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 22 Mar 2025 18:23:14 +0100 Subject: [PATCH 301/503] Make further OpenSSL 1.0.2 clean up Closes GH-18133 --- ext/openssl/openssl.c | 15 ---- ext/openssl/openssl.stub.php | 8 -- ext/openssl/openssl_arginfo.h | 5 +- ext/openssl/openssl_backend_common.c | 39 +-------- ext/openssl/openssl_backend_v1.c | 3 - ext/openssl/openssl_backend_v3.c | 4 - ext/openssl/php_openssl_backend.h | 27 +----- ext/openssl/xp_ssl.c | 121 --------------------------- 8 files changed, 7 insertions(+), 215 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 9be34a5371ab2..0896baf58312a 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3975,20 +3975,11 @@ PHP_FUNCTION(openssl_sign) md_ctx = EVP_MD_CTX_create(); size_t siglen; -#if PHP_OPENSSL_API_VERSION >= 0x10100 if (md_ctx != NULL && EVP_DigestSignInit(md_ctx, NULL, mdtype, NULL, pkey) && EVP_DigestSign(md_ctx, NULL, &siglen, (unsigned char*)data, data_len) && (sigbuf = zend_string_alloc(siglen, 0)) != NULL && EVP_DigestSign(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, (unsigned char*)data, data_len)) { -#else - if (md_ctx != NULL && - EVP_SignInit(md_ctx, mdtype) && - EVP_SignUpdate(md_ctx, data, data_len) && - (siglen = EVP_PKEY_size(pkey)) && - (sigbuf = zend_string_alloc(siglen, 0)) != NULL && - EVP_SignFinal(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), (unsigned int*)&siglen, pkey)) { -#endif ZSTR_VAL(sigbuf)[siglen] = '\0'; ZSTR_LEN(sigbuf) = siglen; ZEND_TRY_ASSIGN_REF_NEW_STR(signature, sigbuf); @@ -4049,14 +4040,8 @@ PHP_FUNCTION(openssl_verify) md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL || -#if PHP_OPENSSL_API_VERSION >= 0x10100 !EVP_DigestVerifyInit(md_ctx, NULL, mdtype, NULL, pkey) || (err = EVP_DigestVerify(md_ctx, (unsigned char *)signature, signature_len, (unsigned char*)data, data_len)) < 0) { -#else - !EVP_VerifyInit (md_ctx, mdtype) || - !EVP_VerifyUpdate (md_ctx, data, data_len) || - (err = EVP_VerifyFinal(md_ctx, (unsigned char *)signature, (unsigned int)signature_len, pkey)) < 0) { -#endif php_openssl_store_errors(); } EVP_MD_CTX_destroy(md_ctx); diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index 1f8c6f7fbdbec..1fe3a9fc168eb 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -86,14 +86,6 @@ */ const OPENSSL_ALGO_MD2 = UNKNOWN; #endif -#if PHP_OPENSSL_API_VERSION < 0x10100 -/** - * @var int - * @cvalue OPENSSL_ALGO_DSS1 - */ -const OPENSSL_ALGO_DSS1 = UNKNOWN; -#endif - /** * @var int * @cvalue OPENSSL_ALGO_SHA224 diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index 04d7c4163db9d..94f59ce268510 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 32bd0ec5db046bfe3bba8a5d3fe1c0c51ff89e00 */ + * Stub hash: a42bd7dec0a5e011983ce08b5e31cd8718247501 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL) @@ -564,9 +564,6 @@ static void register_openssl_symbols(int module_number) #endif #if !defined(OPENSSL_NO_MD2) REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD2", OPENSSL_ALGO_MD2, CONST_PERSISTENT); -#endif -#if PHP_OPENSSL_API_VERSION < 0x10100 - REGISTER_LONG_CONSTANT("OPENSSL_ALGO_DSS1", OPENSSL_ALGO_DSS1, CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA224", OPENSSL_ALGO_SHA224, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA256", OPENSSL_ALGO_SHA256, CONST_PERSISTENT); diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c index 30554a2e3c0a9..44cb22e18d2ab 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -461,7 +461,6 @@ zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int se if (file == NULL) { file = RAND_file_name(buffer, sizeof(buffer)); } - PHP_OPENSSL_RAND_ADD_TIME(); if (file == NULL || !RAND_write_file(file)) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Unable to write random state"); @@ -489,11 +488,6 @@ EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) { case OPENSSL_ALGO_MD2: mdtype = (EVP_MD *) EVP_md2(); break; -#endif -#if PHP_OPENSSL_API_VERSION < 0x10100 - case OPENSSL_ALGO_DSS1: - mdtype = (EVP_MD *) EVP_dss1(); - break; #endif case OPENSSL_ALGO_SHA224: mdtype = (EVP_MD *) EVP_sha224(); @@ -1510,7 +1504,6 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) int egdsocket, seeded; char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE"); php_openssl_load_rand_file(randfile, &egdsocket, &seeded); - PHP_OPENSSL_RAND_ADD_TIME(); EVP_PKEY *key = NULL; EVP_PKEY *params = NULL; @@ -1700,48 +1693,25 @@ void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, const EV int cipher_mode = EVP_CIPHER_mode(cipher_type); memset(mode, 0, sizeof(struct php_openssl_cipher_mode)); switch (cipher_mode) { -#if PHP_OPENSSL_API_VERSION >= 0x10100 - /* Since OpenSSL 1.1, all AEAD ciphers use a common framework. We check for - * EVP_CIPH_OCB_MODE, because LibreSSL does not support it. */ case EVP_CIPH_GCM_MODE: case EVP_CIPH_CCM_MODE: -# ifdef EVP_CIPH_OCB_MODE + /* We check for EVP_CIPH_OCB_MODE, because LibreSSL does not support it. */ +#ifdef EVP_CIPH_OCB_MODE case EVP_CIPH_OCB_MODE: /* For OCB mode, explicitly set the tag length even when decrypting, * see https://github.com/openssl/openssl/issues/8331. */ mode->set_tag_length_always = cipher_mode == EVP_CIPH_OCB_MODE; -# endif +#endif php_openssl_set_aead_flags(mode); mode->set_tag_length_when_encrypting = cipher_mode == EVP_CIPH_CCM_MODE; mode->is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE; break; -# ifdef NID_chacha20_poly1305 +#ifdef NID_chacha20_poly1305 default: if (EVP_CIPHER_nid(cipher_type) == NID_chacha20_poly1305) { php_openssl_set_aead_flags(mode); } break; - -# endif -#else -# ifdef EVP_CIPH_GCM_MODE - case EVP_CIPH_GCM_MODE: - mode->is_aead = 1; - mode->aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG; - mode->aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG; - mode->aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN; - break; -# endif -# ifdef EVP_CIPH_CCM_MODE - case EVP_CIPH_CCM_MODE: - mode->is_aead = 1; - mode->is_single_run_aead = 1; - mode->set_tag_length_when_encrypting = 1; - mode->aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG; - mode->aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG; - mode->aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN; - break; -# endif #endif } } @@ -2121,7 +2091,6 @@ PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_le buffer = zend_string_alloc(buffer_length, 0); PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(buffer_length, length); - PHP_OPENSSL_RAND_ADD_TIME(); if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) { php_openssl_store_errors(); zend_string_release_ex(buffer, 0); diff --git a/ext/openssl/openssl_backend_v1.c b/ext/openssl/openssl_backend_v1.c index dfdb7b014060a..59988451bbbd0 100644 --- a/ext/openssl/openssl_backend_v1.c +++ b/ext/openssl/openssl_backend_v1.c @@ -116,7 +116,6 @@ static bool php_openssl_pkey_init_dsa_data(DSA *dsa, zval *data, bool *is_privat } /* generate key */ - PHP_OPENSSL_RAND_ADD_TIME(); if (!DSA_generate_key(dsa)) { php_openssl_store_errors(); return 0; @@ -185,7 +184,6 @@ static bool php_openssl_pkey_init_dh_data(DH *dh, zval *data, bool *is_private) } /* generate key */ - PHP_OPENSSL_RAND_ADD_TIME(); if (!DH_generate_key(dh)) { php_openssl_store_errors(); return 0; @@ -341,7 +339,6 @@ static bool php_openssl_pkey_init_ec_data(EC_KEY *eckey, zval *data, bool *is_pr if (!EC_KEY_check_key(eckey)) { *is_private = true; - PHP_OPENSSL_RAND_ADD_TIME(); EC_KEY_generate_key(eckey); } diff --git a/ext/openssl/openssl_backend_v3.c b/ext/openssl/openssl_backend_v3.c index b4508b070c738..76965d66e65a7 100644 --- a/ext/openssl/openssl_backend_v3.c +++ b/ext/openssl/openssl_backend_v3.c @@ -143,7 +143,6 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private) pkey = param_key; } else { *is_private = true; - PHP_OPENSSL_RAND_ADD_TIME(); EVP_PKEY_CTX_free(ctx); ctx = EVP_PKEY_CTX_new(param_key, NULL); if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { @@ -219,7 +218,6 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private) pkey = param_key; } else { *is_private = true; - PHP_OPENSSL_RAND_ADD_TIME(); EVP_PKEY_CTX_free(ctx); ctx = EVP_PKEY_CTX_new(param_key, NULL); if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { @@ -407,7 +405,6 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { pkey = param_key; } else { *is_private = true; - PHP_OPENSSL_RAND_ADD_TIME(); if (EVP_PKEY_keygen_init(ctx) != 1 || EVP_PKEY_CTX_set_params(ctx, params) != 1 || EVP_PKEY_generate(ctx, &pkey) != 1) { @@ -482,7 +479,6 @@ void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, z is_private = priv_key != NULL; } else { is_private = true; - PHP_OPENSSL_RAND_ADD_TIME(); if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { goto cleanup; } diff --git a/ext/openssl/php_openssl_backend.h b/ext/openssl/php_openssl_backend.h index f48e3b0761ffb..158b4e27712f9 100644 --- a/ext/openssl/php_openssl_backend.h +++ b/ext/openssl/php_openssl_backend.h @@ -118,9 +118,7 @@ enum php_openssl_encoding { #ifndef OPENSSL_NO_MD2 #define OPENSSL_ALGO_MD2 4 #endif -#if PHP_OPENSSL_API_VERSION < 0x10100 -#define OPENSSL_ALGO_DSS1 5 -#endif +/* Number 5 was used for OPENSSL_ALGO_DSS1 which is no longer available */ #define OPENSSL_ALGO_SHA224 6 #define OPENSSL_ALGO_SHA256 7 #define OPENSSL_ALGO_SHA384 8 @@ -220,23 +218,6 @@ const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo); int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args); void php_openssl_dispose_config(struct php_x509_request * req); - -#if defined(PHP_WIN32) || PHP_OPENSSL_API_VERSION >= 0x10100 -#define PHP_OPENSSL_RAND_ADD_TIME() ((void) 0) -#else -#define PHP_OPENSSL_RAND_ADD_TIME() php_openssl_rand_add_timeval() - -static inline void php_openssl_rand_add_timeval(void) /* {{{ */ -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - RAND_add(&tv, sizeof(tv), 0.0); -} -/* }}} */ - -#endif - zend_result php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded); zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int seeded); @@ -279,7 +260,7 @@ X509_REQ *php_openssl_csr_from_str(zend_string *csr_str, uint32_t arg_num); X509_REQ *php_openssl_csr_from_param( zend_object *csr_obj, zend_string *csr_str, uint32_t arg_num); -#if PHP_OPENSSL_API_VERSION >= 0x10100 && !defined (LIBRESSL_VERSION_NUMBER) +#if !defined (LIBRESSL_VERSION_NUMBER) #define PHP_OPENSSL_ASN1_INTEGER_set ASN1_INTEGER_set_int64 #else #define PHP_OPENSSL_ASN1_INTEGER_set ASN1_INTEGER_set @@ -349,14 +330,12 @@ struct php_openssl_cipher_mode { int aead_ivlen_flag; }; -#if PHP_OPENSSL_API_VERSION >= 0x10100 static inline void php_openssl_set_aead_flags(struct php_openssl_cipher_mode *mode) { mode->is_aead = true; mode->aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG; mode->aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG; mode->aead_ivlen_flag = EVP_CTRL_AEAD_SET_IVLEN; } -#endif void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, const EVP_CIPHER *cipher_type); zend_result php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv_required_len, @@ -375,6 +354,4 @@ zend_result php_openssl_cipher_update(const EVP_CIPHER *cipher_type, const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method); - #endif - diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 92168c16175a1..03c18f9be71a2 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -148,10 +148,6 @@ #define HAVE_IPV6_SAN 1 #endif -#if PHP_OPENSSL_API_VERSION < 0x10100 -static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength); -#endif - extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl); extern zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool raw); extern int php_openssl_get_ssl_stream_data_index(void); @@ -987,45 +983,6 @@ static zend_result php_openssl_set_local_cert(SSL_CTX *ctx, php_stream *stream) } /* }}} */ -#if PHP_OPENSSL_API_VERSION < 0x10100 -static int php_openssl_get_crypto_method_ctx_flags(int method_flags) /* {{{ */ -{ - int ssl_ctx_options = SSL_OP_ALL; - -#ifdef SSL_OP_NO_SSLv2 - ssl_ctx_options |= SSL_OP_NO_SSLv2; -#endif -#ifdef HAVE_SSL3 - if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv3)) { - ssl_ctx_options |= SSL_OP_NO_SSLv3; - } -#endif -#ifdef HAVE_TLS1 - if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_0)) { - ssl_ctx_options |= SSL_OP_NO_TLSv1; - } -#endif -#ifdef HAVE_TLS11 - if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_1)) { - ssl_ctx_options |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef HAVE_TLS12 - if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_2)) { - ssl_ctx_options |= SSL_OP_NO_TLSv1_2; - } -#endif -#ifdef HAVE_TLS13 - if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_3)) { - ssl_ctx_options |= SSL_OP_NO_TLSv1_3; - } -#endif - - return ssl_ctx_options; -} -/* }}} */ -#endif - static inline int php_openssl_get_min_proto_version_flag(int flags) /* {{{ */ { int ver; @@ -1050,7 +1007,6 @@ static inline int php_openssl_get_max_proto_version_flag(int flags) /* {{{ */ } /* }}} */ -#if PHP_OPENSSL_API_VERSION >= 0x10100 static inline int php_openssl_map_proto_version(int flag) /* {{{ */ { switch (flag) { @@ -1085,7 +1041,6 @@ static int php_openssl_get_max_proto_version(int flags) /* {{{ */ return php_openssl_map_proto_version(php_openssl_get_max_proto_version_flag(flags)); } /* }}} */ -#endif static int php_openssl_get_proto_version_flags(int flags, int min, int max) /* {{{ */ { @@ -1219,30 +1174,6 @@ static void php_openssl_init_server_reneg_limit(php_stream *stream, php_openssl_ } /* }}} */ -#if PHP_OPENSSL_API_VERSION < 0x10100 -static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength) -{ - BIGNUM *bn = NULL; - static RSA *rsa_tmp = NULL; - - if (!rsa_tmp && ((bn = BN_new()) == NULL)) { - php_error_docref(NULL, E_WARNING, "allocation error generating RSA key"); - } - if (!rsa_tmp && bn) { - if (!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) || - !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) { - if (rsa_tmp) { - RSA_free(rsa_tmp); - } - rsa_tmp = NULL; - } - BN_free(bn); - } - - return (rsa_tmp); -} -#endif - static zend_result php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* {{{ */ { zval *zdhpath = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param"); @@ -1303,57 +1234,11 @@ static zend_result php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX } /* }}} */ -#if defined(HAVE_ECDH) && PHP_OPENSSL_API_VERSION < 0x10100 -static zend_result php_openssl_set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx) /* {{{ */ -{ - zval *zvcurve; - int curve_nid; - EC_KEY *ecdh; - - zvcurve = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "ecdh_curve"); - if (zvcurve == NULL) { - SSL_CTX_set_ecdh_auto(ctx, 1); - return SUCCESS; - } else { - if (!try_convert_to_string(zvcurve)) { - return FAILURE; - } - - curve_nid = OBJ_sn2nid(Z_STRVAL_P(zvcurve)); - if (curve_nid == NID_undef) { - php_error_docref(NULL, E_WARNING, "Invalid ecdh_curve specified"); - return FAILURE; - } - } - - ecdh = EC_KEY_new_by_curve_name(curve_nid); - if (ecdh == NULL) { - php_error_docref(NULL, E_WARNING, "Failed generating ECDH curve"); - return FAILURE; - } - - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); - - return SUCCESS; -} -/* }}} */ -#endif - static zend_result php_openssl_set_server_specific_opts(php_stream *stream, SSL_CTX *ctx) /* {{{ */ { zval *zv; long ssl_ctx_options = SSL_CTX_get_options(ctx); -#if defined(HAVE_ECDH) && PHP_OPENSSL_API_VERSION < 0x10100 - if (php_openssl_set_server_ecdh_curve(stream, ctx) == FAILURE) { - return FAILURE; - } -#endif - -#if PHP_OPENSSL_API_VERSION < 0x10100 - SSL_CTX_set_tmp_rsa_callback(ctx, php_openssl_tmp_rsa_cb); -#endif /* We now use php_openssl_tmp_rsa_cb to generate a key of appropriate size whenever necessary */ if (php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "rsa_key_size") != NULL) { php_error_docref(NULL, E_WARNING, "rsa_key_size context option has been removed"); @@ -1690,11 +1575,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, GET_VER_OPT_LONG("min_proto_version", min_version); GET_VER_OPT_LONG("max_proto_version", max_version); method_flags = php_openssl_get_proto_version_flags(method_flags, min_version, max_version); -#if PHP_OPENSSL_API_VERSION < 0x10100 - ssl_ctx_options = php_openssl_get_crypto_method_ctx_flags(method_flags); -#else ssl_ctx_options = SSL_OP_ALL; -#endif if (GET_VER_OPT("no_ticket") && zend_is_true(val)) { ssl_ctx_options |= SSL_OP_NO_TICKET; @@ -1780,10 +1661,8 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); -#if PHP_OPENSSL_API_VERSION >= 0x10100 SSL_CTX_set_min_proto_version(sslsock->ctx, php_openssl_get_min_proto_version(method_flags)); SSL_CTX_set_max_proto_version(sslsock->ctx, php_openssl_get_max_proto_version(method_flags)); -#endif if (sslsock->is_client == 0 && PHP_STREAM_CONTEXT(stream) && From 6d458caefedf34f9086120178aae4e9bcb440270 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 7 Apr 2025 17:33:47 +0200 Subject: [PATCH 302/503] Fix prop info fetching from prop slot with added hooks Fixes GH-18268 Closes GH-18271 --- NEWS | 2 ++ Zend/tests/property_hooks/gh18268.phpt | 23 +++++++++++++++++++++++ Zend/zend_compile.h | 2 ++ Zend/zend_objects_API.c | 2 +- 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/property_hooks/gh18268.phpt diff --git a/NEWS b/NEWS index 1aeb22dfb0671..af8017fe151b0 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS evaluation). (ilutov) . Fixed bug GH-18038 (Lazy proxy calls magic methods twice). (Arnaud) . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) + . Fixed bug GH-18268 (Segfault in array_walk() on object with added property + hooks). (ilutov) - DBA: . FIxed bug GH-18247 dba_popen() memory leak on invalid path. (David Carlier) diff --git a/Zend/tests/property_hooks/gh18268.phpt b/Zend/tests/property_hooks/gh18268.phpt new file mode 100644 index 0000000000000..9836bb6d96270 --- /dev/null +++ b/Zend/tests/property_hooks/gh18268.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-18268: array_walk() on object with added property hooks +--FILE-- + +--EXPECT-- +int(42) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 7f425852d01b4..b2e7de4c343ae 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -464,6 +464,8 @@ typedef struct _zend_property_info { ((uint32_t)(XtOffsetOf(zend_object, properties_table) + sizeof(zval) * (num))) #define OBJ_PROP_TO_NUM(offset) \ (((offset) - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval)) +#define OBJ_PROP_SLOT_TO_OFFSET(obj, slot) \ + ((uintptr_t)(slot) - (uintptr_t)(obj)) typedef struct _zend_class_constant { zval value; /* flags are stored in u2 */ diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 1ba250bec6439..9b1b6dd4fcbb4 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -203,7 +203,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ * ZEND_API ZEND_COLD zend_property_info *zend_get_property_info_for_slot_slow(zend_object *obj, zval *slot) { - uintptr_t offset = (uintptr_t)slot - (uintptr_t)obj->properties_table; + uintptr_t offset = OBJ_PROP_SLOT_TO_OFFSET(obj, slot); zend_property_info *prop_info; ZEND_HASH_MAP_FOREACH_PTR(&obj->ce->properties_info, prop_info) { if (prop_info->offset == offset) { From 2d39c7855a9397f1d00546955fd9e92963db6a17 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 8 Apr 2025 22:43:11 +0100 Subject: [PATCH 303/503] Fixed GH-18267 finfo_file() crashing on invalid URL protocol. (#18269) Close GH-18267 --- ext/fileinfo/fileinfo.c | 3 +++ ext/fileinfo/tests/gh18267.phpt | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 ext/fileinfo/tests/gh18267.phpt diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index d3680c5755f25..c0cc8877bf991 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -344,6 +344,9 @@ PHP_FUNCTION(finfo_file) RETURN_THROWS(); } php_stream_context *context = php_stream_context_from_zval(zcontext, false); + if (!context) { + RETURN_THROWS(); + } /* Set options for the current file/buffer. */ if (options) { diff --git a/ext/fileinfo/tests/gh18267.phpt b/ext/fileinfo/tests/gh18267.phpt new file mode 100644 index 0000000000000..ba7647288d1de --- /dev/null +++ b/ext/fileinfo/tests/gh18267.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-18267 finfo_file() assertion trigger on NULL stream context +--EXTENSIONS-- +fileinfo +--FILE-- +file("test",FILEINFO_NONE, STDERR); +} catch (\TypeError $e) { + echo $e->getMessage(); +} +--EXPECT-- +finfo::file(): supplied resource is not a valid Stream-Context resource From c20b429a90eb79166517752990947aa623aabfbc Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Sun, 9 Mar 2025 16:12:51 +0700 Subject: [PATCH 304/503] ext/intl: Add `NumberFormatter::CURRENCY_ISO`, `PLURAL`, `STANDARD` and `CASH_CURRENCY` ICU 54 and 56 adds the following formatters[^1] for currency formatting: - `CURRENCY_ISO`[^2]: ISO currency code, e.g., "USD1.00" - `CURRENCY_PLURAL`[^3]: pluralized currency name, e.g., "1.00 US dollar" and "3.00 US dollars" - `CASH_CURRENCY`[^4]: currency symbol given CASH usage, e.g., "NT$3" instead of "NT$3.23" - `CURRENCY_STANDARD`[^5]: currency symbol, e.g., "$1.00", using non-accounting style for negative values (e.g. minus sign) Ref: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html This adds support for all four of them to ext/intl, along with tests. [^1]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html [^2]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266daae232c48e579c727525855cd21571033 [^3]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266da3916bb92d0784396ea2331d4f04c03f5 [^4]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266da8da9eba1a27d5734599709c137c3b82f [^5]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266dac57cfff1b245d11774e8b109b98eedc2 --- ext/intl/formatter/formatter.stub.php | 8 + ext/intl/formatter/formatter_arginfo.h | 26 ++- ext/intl/tests/formatter/currencies.phpt | 191 +++++++++++++++++++++++ 3 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/formatter/currencies.phpt diff --git a/ext/intl/formatter/formatter.stub.php b/ext/intl/formatter/formatter.stub.php index 4445005c41705..ca94a2652bbe4 100644 --- a/ext/intl/formatter/formatter.stub.php +++ b/ext/intl/formatter/formatter.stub.php @@ -31,8 +31,16 @@ class NumberFormatter public const int PATTERN_RULEBASED = UNKNOWN; /** @cvalue UNUM_IGNORE */ public const int IGNORE = UNKNOWN; + /** @cvalue UNUM_CURRENCY_ISO */ + public const int CURRENCY_ISO = UNKNOWN; + /** @cvalue UNUM_CURRENCY_PLURAL */ + public const int CURRENCY_PLURAL = UNKNOWN; /** @cvalue UNUM_CURRENCY_ACCOUNTING */ public const int CURRENCY_ACCOUNTING = UNKNOWN; + /** @cvalue UNUM_CASH_CURRENCY */ + public const int CASH_CURRENCY = UNKNOWN; + /** @cvalue UNUM_CURRENCY_STANDARD */ + public const int CURRENCY_STANDARD = UNKNOWN; /** @cvalue UNUM_DEFAULT */ public const int DEFAULT_STYLE = UNKNOWN; diff --git a/ext/intl/formatter/formatter_arginfo.h b/ext/intl/formatter/formatter_arginfo.h index c7fd28c3a9f77..b872b0dc20f46 100644 --- a/ext/intl/formatter/formatter_arginfo.h +++ b/ext/intl/formatter/formatter_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 05ab9fb3ba33163b2100e2773d70f67e110ecefc */ + * Stub hash: d886941aa76837aed1da08845dbaff9442107203 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter___construct, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) @@ -197,12 +197,36 @@ static zend_class_entry *register_class_NumberFormatter(void) zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_IGNORE_name); + zval const_CURRENCY_ISO_value; + ZVAL_LONG(&const_CURRENCY_ISO_value, UNUM_CURRENCY_ISO); + zend_string *const_CURRENCY_ISO_name = zend_string_init_interned("CURRENCY_ISO", sizeof("CURRENCY_ISO") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_CURRENCY_ISO_name, &const_CURRENCY_ISO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_CURRENCY_ISO_name); + + zval const_CURRENCY_PLURAL_value; + ZVAL_LONG(&const_CURRENCY_PLURAL_value, UNUM_CURRENCY_PLURAL); + zend_string *const_CURRENCY_PLURAL_name = zend_string_init_interned("CURRENCY_PLURAL", sizeof("CURRENCY_PLURAL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_CURRENCY_PLURAL_name, &const_CURRENCY_PLURAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_CURRENCY_PLURAL_name); + zval const_CURRENCY_ACCOUNTING_value; ZVAL_LONG(&const_CURRENCY_ACCOUNTING_value, UNUM_CURRENCY_ACCOUNTING); zend_string *const_CURRENCY_ACCOUNTING_name = zend_string_init_interned("CURRENCY_ACCOUNTING", sizeof("CURRENCY_ACCOUNTING") - 1, 1); zend_declare_typed_class_constant(class_entry, const_CURRENCY_ACCOUNTING_name, &const_CURRENCY_ACCOUNTING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_CURRENCY_ACCOUNTING_name); + zval const_CASH_CURRENCY_value; + ZVAL_LONG(&const_CASH_CURRENCY_value, UNUM_CASH_CURRENCY); + zend_string *const_CASH_CURRENCY_name = zend_string_init_interned("CASH_CURRENCY", sizeof("CASH_CURRENCY") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_CASH_CURRENCY_name, &const_CASH_CURRENCY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_CASH_CURRENCY_name); + + zval const_CURRENCY_STANDARD_value; + ZVAL_LONG(&const_CURRENCY_STANDARD_value, UNUM_CURRENCY_STANDARD); + zend_string *const_CURRENCY_STANDARD_name = zend_string_init_interned("CURRENCY_STANDARD", sizeof("CURRENCY_STANDARD") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_CURRENCY_STANDARD_name, &const_CURRENCY_STANDARD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_CURRENCY_STANDARD_name); + zval const_DEFAULT_STYLE_value; ZVAL_LONG(&const_DEFAULT_STYLE_value, UNUM_DEFAULT); zend_string *const_DEFAULT_STYLE_name = zend_string_init_interned("DEFAULT_STYLE", sizeof("DEFAULT_STYLE") - 1, 1); diff --git a/ext/intl/tests/formatter/currencies.phpt b/ext/intl/tests/formatter/currencies.phpt new file mode 100644 index 0000000000000..01c64a0480d37 --- /dev/null +++ b/ext/intl/tests/formatter/currencies.phpt @@ -0,0 +1,191 @@ +--TEST-- +NumberFormatter: currency formatting +----DESCRIPTION-- +Tests NumberFormatter with various currenct-related formatters. +--EXTENSIONS-- +intl +--FILE-- + NumberFormatter::CURRENCY, + 'CURRENCY_ACCOUNTING' => NumberFormatter::CURRENCY_ACCOUNTING, + 'CURRENCY_ISO' => NumberFormatter::CURRENCY_ISO, + 'CURRENCY_PLURAL' => NumberFormatter::CURRENCY_PLURAL, + 'CASH_CURRENCY' => NumberFormatter::CASH_CURRENCY, + 'CURRENCY_STANDARD' => NumberFormatter::CURRENCY_STANDARD, + ]; + + $numbers = [0, 1, 2, 123456789.42, -123456789.42, 456.789012]; + + $res_str = ''; + + foreach($locales as $locale) { + foreach ($formats as $formatLabel => $format) { + $res_str .= "$locale: $formatLabel\n"; + foreach ($numbers as $number) { + $fmt = ut_nfmt_create($locale, $format); + $res_str .= "$number => " . ut_nfmt_format_currency($fmt, $number, ut_nfmt_get_symbol($fmt, NumberFormatter::INTL_CURRENCY_SYMBOL)) . "\n"; + } + $res_str .= "\n"; + } + } + + return $res_str; +} + +include_once(__DIR__ . '/../ut_common.inc'); + +ut_run(); +?> +--EXPECT-- +ka-GE: CURRENCY +0 => 0,00 ₾ +1 => 1,00 ₾ +2 => 2,00 ₾ +123456789.42 => 123 456 789,42 ₾ +-123456789.42 => -123 456 789,42 ₾ +456.789012 => 456,79 ₾ + +ka-GE: CURRENCY_ACCOUNTING +0 => 0,00 ₾ +1 => 1,00 ₾ +2 => 2,00 ₾ +123456789.42 => 123 456 789,42 ₾ +-123456789.42 => -123 456 789,42 ₾ +456.789012 => 456,79 ₾ + +ka-GE: CURRENCY_ISO +0 => 0,00 GEL +1 => 1,00 GEL +2 => 2,00 GEL +123456789.42 => 123 456 789,42 GEL +-123456789.42 => -123 456 789,42 GEL +456.789012 => 456,79 GEL + +ka-GE: CURRENCY_PLURAL +0 => 0,00 ქართული ლარი +1 => 1,00 ქართული ლარი +2 => 2,00 ქართული ლარი +123456789.42 => 123 456 789,42 ქართული ლარი +-123456789.42 => -123 456 789,42 ქართული ლარი +456.789012 => 456,79 ქართული ლარი + +ka-GE: CASH_CURRENCY +0 => 0,00 ₾ +1 => 1,00 ₾ +2 => 2,00 ₾ +123456789.42 => 123 456 789,42 ₾ +-123456789.42 => -123 456 789,42 ₾ +456.789012 => 456,79 ₾ + +ka-GE: CURRENCY_STANDARD +0 => 0,00 ₾ +1 => 1,00 ₾ +2 => 2,00 ₾ +123456789.42 => 123 456 789,42 ₾ +-123456789.42 => -123 456 789,42 ₾ +456.789012 => 456,79 ₾ + +hi-IN: CURRENCY +0 => ₹0.00 +1 => ₹1.00 +2 => ₹2.00 +123456789.42 => ₹12,34,56,789.42 +-123456789.42 => -₹12,34,56,789.42 +456.789012 => ₹456.79 + +hi-IN: CURRENCY_ACCOUNTING +0 => ₹0.00 +1 => ₹1.00 +2 => ₹2.00 +123456789.42 => ₹12,34,56,789.42 +-123456789.42 => -₹12,34,56,789.42 +456.789012 => ₹456.79 + +hi-IN: CURRENCY_ISO +0 => INR 0.00 +1 => INR 1.00 +2 => INR 2.00 +123456789.42 => INR 12,34,56,789.42 +-123456789.42 => -INR 12,34,56,789.42 +456.789012 => INR 456.79 + +hi-IN: CURRENCY_PLURAL +0 => 0.00 भारतीय रुपया +1 => 1.00 भारतीय रुपया +2 => 2.00 भारतीय रुपए +123456789.42 => 12,34,56,789.42 भारतीय रुपए +-123456789.42 => -12,34,56,789.42 भारतीय रुपए +456.789012 => 456.79 भारतीय रुपए + +hi-IN: CASH_CURRENCY +0 => ₹0.00 +1 => ₹1.00 +2 => ₹2.00 +123456789.42 => ₹12,34,56,789.42 +-123456789.42 => -₹12,34,56,789.42 +456.789012 => ₹456.79 + +hi-IN: CURRENCY_STANDARD +0 => ₹0.00 +1 => ₹1.00 +2 => ₹2.00 +123456789.42 => ₹12,34,56,789.42 +-123456789.42 => -₹12,34,56,789.42 +456.789012 => ₹456.79 + +zh-TW: CURRENCY +0 => $0.00 +1 => $1.00 +2 => $2.00 +123456789.42 => $123,456,789.42 +-123456789.42 => -$123,456,789.42 +456.789012 => $456.79 + +zh-TW: CURRENCY_ACCOUNTING +0 => $0.00 +1 => $1.00 +2 => $2.00 +123456789.42 => $123,456,789.42 +-123456789.42 => ($123,456,789.42) +456.789012 => $456.79 + +zh-TW: CURRENCY_ISO +0 => TWD 0.00 +1 => TWD 1.00 +2 => TWD 2.00 +123456789.42 => TWD 123,456,789.42 +-123456789.42 => -TWD 123,456,789.42 +456.789012 => TWD 456.79 + +zh-TW: CURRENCY_PLURAL +0 => 0.00 新台幣 +1 => 1.00 新台幣 +2 => 2.00 新台幣 +123456789.42 => 123,456,789.42 新台幣 +-123456789.42 => -123,456,789.42 新台幣 +456.789012 => 456.79 新台幣 + +zh-TW: CASH_CURRENCY +0 => $0 +1 => $1 +2 => $2 +123456789.42 => $123,456,789 +-123456789.42 => -$123,456,789 +456.789012 => $457 + +zh-TW: CURRENCY_STANDARD +0 => $0.00 +1 => $1.00 +2 => $2.00 +123456789.42 => $123,456,789.42 +-123456789.42 => -$123,456,789.42 +456.789012 => $456.79 From 195467f014f4486d76fe3ee625bffefc647be658 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 30 Jan 2025 11:20:52 +0100 Subject: [PATCH 305/503] [ext-curl] Add `\CURLOPT_INFILESIZE_LARGE` This is my first PR on this repository and is based on: * https://github.com/symfony/symfony/pull/59654/files#r1935358570 So feel free to close it :-) --- ext/curl/curl.stub.php | 5 +++++ ext/curl/curl_arginfo.h | 3 ++- ext/curl/interface.c | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index c9abe237339b5..6a73913f8a85e 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -188,6 +188,11 @@ * @cvalue CURLOPT_INFILESIZE */ const CURLOPT_INFILESIZE = UNKNOWN; +/** + * @var int + * @cvalue CURLOPT_INFILESIZE_LARGE + */ +const CURLOPT_INFILESIZE_LARGE = UNKNOWN; /** * @var int * @cvalue CURLOPT_INTERFACE diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index 6a81d1e92c88f..53a59fe47be49 100644 --- a/ext/curl/curl_arginfo.h +++ b/ext/curl/curl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 48fc95503f4f8cc96575ff6f31fdd1e4cdc5969e */ + * Stub hash: 77da3a34f08b3e932a0545f72b41bf0353e8b157 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) @@ -263,6 +263,7 @@ static void register_curl_symbols(int module_number) REGISTER_LONG_CONSTANT("CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_INFILE", CURLOPT_INFILE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_INFILESIZE", CURLOPT_INFILESIZE, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_INTERFACE", CURLOPT_INTERFACE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT, CONST_PERSISTENT); diff --git a/ext/curl/interface.c b/ext/curl/interface.c index aebb336378bc0..8458cd77dabd2 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2244,6 +2244,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue break; /* Curl off_t options */ + case CURLOPT_INFILESIZE_LARGE: case CURLOPT_MAX_RECV_SPEED_LARGE: case CURLOPT_MAX_SEND_SPEED_LARGE: case CURLOPT_MAXFILESIZE_LARGE: From 7fd51535a44fd9cc7cf804e91cc7e6e0b742f5b1 Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Wed, 9 Apr 2025 04:08:48 +0700 Subject: [PATCH 306/503] ext/curl: add tests for `CURLOPT_INFILESIZE(_LARGE)` --- ext/curl/tests/Caddyfile | 5 ++ .../curl_setopt_CURLOPT_INFILESIZE_LARGE.phpt | 58 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_INFILESIZE_LARGE.phpt diff --git a/ext/curl/tests/Caddyfile b/ext/curl/tests/Caddyfile index 30686f0bb9fa2..67b82434ba4c6 100644 --- a/ext/curl/tests/Caddyfile +++ b/ext/curl/tests/Caddyfile @@ -12,6 +12,11 @@ respond /serverpush "main response" respond /serverpush/pushed "pushed response" push /serverpush /serverpush/pushed +route /show_upload_size { + templates + respond `Content-length: ={{.Req.Header.Get "Content-length"}}=` +} + basic_auth /http-basic-auth { # bcrypt password hash for "password", calculated with 'caddy hash-password' user $2a$14$yUKl9SGqVTAAqPTzLup.DefsbXXx3kfreNnzpJOUHcIrKnr5lgef2 diff --git a/ext/curl/tests/curl_setopt_CURLOPT_INFILESIZE_LARGE.phpt b/ext/curl/tests/curl_setopt_CURLOPT_INFILESIZE_LARGE.phpt new file mode 100644 index 0000000000000..5063958412b5a --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_INFILESIZE_LARGE.phpt @@ -0,0 +1,58 @@ +--TEST-- +Curl option CURLOPT_INFILESIZE_LARGE +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + true, + CURLOPT_UPLOAD => true, + CURLOPT_INFILE => $f, + CURLOPT_INFILESIZE => filesize(__FILE__), + CURLOPT_CONNECTTIMEOUT => 3, + CURLOPT_TIMEOUT => 3, + CURLOPT_SSL_VERIFYHOST => 0, + CURLOPT_SSL_VERIFYPEER => 0, +])); + +var_dump(curl_exec($ch)); + +var_dump(curl_setopt($ch, CURLOPT_INFILESIZE, -1)); +var_dump(curl_exec($ch)); + +var_dump(curl_setopt($ch, CURLOPT_INFILESIZE_LARGE, -1)); +var_dump(curl_exec($ch)); + +rewind($f); +var_dump(curl_setopt($ch, CURLOPT_INFILESIZE, filesize(__FILE__))); +var_dump(curl_exec($ch)); +var_dump(curl_setopt($ch, CURLOPT_INFILESIZE_LARGE, -1)); +var_dump(curl_exec($ch)); + +rewind($f); +var_dump(curl_setopt($ch, CURLOPT_INFILESIZE_LARGE, filesize(__FILE__))); +var_dump(curl_exec($ch)); + +var_dump(curl_error($ch)); + +?> +--EXPECTF-- +bool(true) +string(21) "Content-length: =%d=" +bool(true) +string(18) "Content-length: ==" +bool(true) +string(18) "Content-length: ==" +bool(true) +string(21) "Content-length: =%d=" +bool(true) +string(18) "Content-length: ==" +bool(true) +string(21) "Content-length: =%d=" +string(0) "" From 895905b85a2ab01e9256445b383d678fb94b1bf2 Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Wed, 9 Apr 2025 04:30:28 +0700 Subject: [PATCH 307/503] ext/curl: Add CURLOPT_INFILESIZE_LARGE to UPGRADING --- UPGRADING | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UPGRADING b/UPGRADING index 6cc0cc537df2d..451cfe4b86b3e 100644 --- a/UPGRADING +++ b/UPGRADING @@ -147,6 +147,11 @@ PHP 8.5 UPGRADE NOTES indicating the http and proxy authentication methods that were used in the previous request. See CURLAUTH_* constants for possible values. + . Added CURLOPT_INFILESIZE_LARGE Curl option, which is a safe + replacement for CURLOPT_INFILESIZE. On certain systems, + CURLOPT_INFILESIZE only accepts a 32-bit signed integer as the file + size (2.0 GiB) even on 64-bit systems. CURLOPT_INFILESIZE_LARGE + accepts the largest integer value the system can handle. - DOM: . Added Dom\Element::$outerHTML. @@ -343,6 +348,7 @@ PHP 8.5 UPGRADE NOTES . CURLINFO_USED_PROXY. . CURLINFO_HTTPAUTH_USED. . CURLINFO_PROXYAUTH_USED. + . CURLOPT_INFILESIZE_LARGE. - Intl: . DECIMAL_COMPACT_SHORT. From 787f26c8827baa4fa6ed554fa4562750cc86d1a6 Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Wed, 9 Apr 2025 14:20:33 +0700 Subject: [PATCH 308/503] UPGRADING: Add notice for the new NumberFormatter::CURRENCY constants --- UPGRADING | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UPGRADING b/UPGRADING index 451cfe4b86b3e..3d69637d51797 100644 --- a/UPGRADING +++ b/UPGRADING @@ -159,6 +159,12 @@ PHP 8.5 UPGRADE NOTES - EXIF: . Add OffsetTime* Exif tags. +- Intl: + . Added class constants NumberFormatter::CURRENCY_ISO, + NumberFormatter::CURRENCY_PLURAL, NumberFormatter::CASH_CURRENCY, + and NumberFormatter::CURRENCY_STANDARD for various currency-related + number formats. + - XSL: . The $namespace argument of XSLTProcessor::getParameter(), XSLTProcessor::setParameter() and XSLTProcessor::removeParameter() From 389de7c6bf59e14145e932f4d3c0171803a3ba97 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 26 Feb 2025 17:26:08 +0100 Subject: [PATCH 309/503] Fix #17776 LDAP_OPT_X_TLS_REQUIRE_CERT can't be overridden --- ext/ldap/ldap.c | 89 ++++++++++++++++++------ ext/ldap/php_ldap.h | 1 + ext/ldap/tests/ldap_start_tls_basic.phpt | 21 +++++- ext/ldap/tests/ldaps_basic.phpt | 55 +++++++++++++++ 4 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 ext/ldap/tests/ldaps_basic.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index db4c5ab231042..1a878bfc58483 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -835,6 +835,21 @@ static PHP_GINIT_FUNCTION(ldap) } /* }}} */ +/* {{{ PHP_RINIT_FUNCTION */ +static PHP_RINIT_FUNCTION(ldap) +{ +#if defined(COMPILE_DL_LDAP) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + + /* needed before first connect and after TLS option changes */ + LDAPG(tls_newctx) = true; + + return SUCCESS; +} +/* }}} */ + + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(ldap) { @@ -987,6 +1002,20 @@ PHP_FUNCTION(ldap_connect) snprintf( url, urllen, "ldap://%s:" ZEND_LONG_FMT, host, port ); } +#ifdef LDAP_OPT_X_TLS_NEWCTX + if (LDAPG(tls_newctx) && url && !strncmp(url, "ldaps:", 6)) { + int val = 0; + + /* ensure all pending TLS options are applied in a new context */ + if (ldap_set_option(NULL, LDAP_OPT_X_TLS_NEWCTX, &val) != LDAP_OPT_SUCCESS) { + zval_ptr_dtor(return_value); + php_error_docref(NULL, E_WARNING, "Could not create new security context"); + RETURN_FALSE; + } + LDAPG(tls_newctx) = false; + } +#endif + #ifdef LDAP_API_FEATURE_X_OPENLDAP /* ldap_init() is deprecated, use ldap_initialize() instead. */ @@ -3172,15 +3201,7 @@ PHP_FUNCTION(ldap_set_option) } switch (option) { - /* options with int value */ - case LDAP_OPT_DEREF: - case LDAP_OPT_SIZELIMIT: - case LDAP_OPT_TIMELIMIT: - case LDAP_OPT_PROTOCOL_VERSION: - case LDAP_OPT_ERROR_NUMBER: -#ifdef LDAP_OPT_DEBUG_LEVEL - case LDAP_OPT_DEBUG_LEVEL: -#endif + /* TLS options with int value */ #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT case LDAP_OPT_X_TLS_REQUIRE_CERT: #endif @@ -3189,6 +3210,18 @@ PHP_FUNCTION(ldap_set_option) #endif #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN case LDAP_OPT_X_TLS_PROTOCOL_MIN: +#endif + /* TLS option change requires resetting TLS context */ + LDAPG(tls_newctx) = true; + ZEND_FALLTHROUGH; + /* other options with int value */ + case LDAP_OPT_DEREF: + case LDAP_OPT_SIZELIMIT: + case LDAP_OPT_TIMELIMIT: + case LDAP_OPT_PROTOCOL_VERSION: + case LDAP_OPT_ERROR_NUMBER: +#ifdef LDAP_OPT_DEBUG_LEVEL + case LDAP_OPT_DEBUG_LEVEL: #endif #ifdef LDAP_OPT_X_KEEPALIVE_IDLE case LDAP_OPT_X_KEEPALIVE_IDLE: @@ -3245,17 +3278,7 @@ PHP_FUNCTION(ldap_set_option) } } break; #endif - /* options with string value */ - case LDAP_OPT_ERROR_STRING: -#ifdef LDAP_OPT_HOST_NAME - case LDAP_OPT_HOST_NAME: -#endif -#ifdef HAVE_LDAP_SASL - case LDAP_OPT_X_SASL_MECH: - case LDAP_OPT_X_SASL_REALM: - case LDAP_OPT_X_SASL_AUTHCID: - case LDAP_OPT_X_SASL_AUTHZID: -#endif + /* TLS options with string value */ #if (LDAP_API_VERSION > 2000) case LDAP_OPT_X_TLS_CACERTDIR: case LDAP_OPT_X_TLS_CACERTFILE: @@ -3269,6 +3292,20 @@ PHP_FUNCTION(ldap_set_option) #endif #ifdef LDAP_OPT_X_TLS_DHFILE case LDAP_OPT_X_TLS_DHFILE: +#endif + /* TLS option change requires resetting TLS context */ + LDAPG(tls_newctx) = true; + ZEND_FALLTHROUGH; + /* other options with string value */ + case LDAP_OPT_ERROR_STRING: +#ifdef LDAP_OPT_HOST_NAME + case LDAP_OPT_HOST_NAME: +#endif +#ifdef HAVE_LDAP_SASL + case LDAP_OPT_X_SASL_MECH: + case LDAP_OPT_X_SASL_REALM: + case LDAP_OPT_X_SASL_AUTHCID: + case LDAP_OPT_X_SASL_AUTHZID: #endif #ifdef LDAP_OPT_MATCHED_DN case LDAP_OPT_MATCHED_DN: @@ -3688,6 +3725,9 @@ PHP_FUNCTION(ldap_start_tls) zval *link; ldap_linkdata *ld; int rc, protocol = LDAP_VERSION3; +#ifdef LDAP_OPT_X_TLS_NEWCTX + int val = 0; +#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) { RETURN_THROWS(); @@ -3697,13 +3737,16 @@ PHP_FUNCTION(ldap_start_tls) VERIFY_LDAP_LINK_CONNECTED(ld); if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) || +#ifdef LDAP_OPT_X_TLS_NEWCTX + (LDAPG(tls_newctx) && (rc = ldap_set_option(ld->link, LDAP_OPT_X_TLS_NEWCTX, &val)) != LDAP_OPT_SUCCESS) || +#endif ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS) ) { php_error_docref(NULL, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc)); RETURN_FALSE; - } else { - RETURN_TRUE; } + LDAPG(tls_newctx) = false; + RETURN_TRUE; } /* }}} */ #endif @@ -4218,7 +4261,7 @@ zend_module_entry ldap_module_entry = { /* {{{ */ ext_functions, PHP_MINIT(ldap), PHP_MSHUTDOWN(ldap), - NULL, + PHP_RINIT(ldap), NULL, PHP_MINFO(ldap), PHP_LDAP_VERSION, diff --git a/ext/ldap/php_ldap.h b/ext/ldap/php_ldap.h index 5581f5b7671a8..a8c4a77af8010 100644 --- a/ext/ldap/php_ldap.h +++ b/ext/ldap/php_ldap.h @@ -39,6 +39,7 @@ PHP_MINFO_FUNCTION(ldap); ZEND_BEGIN_MODULE_GLOBALS(ldap) zend_long num_links; zend_long max_links; + bool tls_newctx; /* create new TLS context before connect */ ZEND_END_MODULE_GLOBALS(ldap) #if defined(ZTS) && defined(COMPILE_DL_LDAP) diff --git a/ext/ldap/tests/ldap_start_tls_basic.phpt b/ext/ldap/tests/ldap_start_tls_basic.phpt index 4dbdce034369f..b8816de9ac4f5 100644 --- a/ext/ldap/tests/ldap_start_tls_basic.phpt +++ b/ext/ldap/tests/ldap_start_tls_basic.phpt @@ -9,11 +9,28 @@ ldap --FILE-- --EXPECT-- +bool(false) bool(true) +bool(false) diff --git a/ext/ldap/tests/ldaps_basic.phpt b/ext/ldap/tests/ldaps_basic.phpt new file mode 100644 index 0000000000000..7a1a1383436d7 --- /dev/null +++ b/ext/ldap/tests/ldaps_basic.phpt @@ -0,0 +1,55 @@ +--TEST-- +ldap_connect() - Basic ldaps test +--EXTENSIONS-- +ldap +--XFAIL-- +Passes locally but fails on CI - need investigation (configuration ?) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) From 98fb27a5775a1d73029822280c7c67128008aa54 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 10 Apr 2025 17:09:03 +0200 Subject: [PATCH 310/503] NEWS for GH-17940 --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 71430bc20b0ff..416d97aeee93f 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS . Fixed GH-18243 imagettftext() overflow/underflow on font size value. (David Carlier) +- LDAP: + . Fixed bug GH-17940 (LDAP_OPT_X_TLS_REQUIRE_CERT can't be overridden). (Remi) + - libxml: . Fixed custom external entity loader returning an invalid resource leading to a confusing TypeError message. (Girgias) From b3a43ca7a46a4a77c2497d60660473ab2fed9ca4 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 10 Apr 2025 17:14:03 +0200 Subject: [PATCH 311/503] NEWS for GH-17940 --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index af8017fe151b0..8f165880aa8fa 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ PHP NEWS . Fixed GH-18243 imagettftext() overflow/underflow on font size value. (David Carlier) +- LDAP: + . Fixed bug GH-17940 (LDAP_OPT_X_TLS_REQUIRE_CERT can't be overridden). (Remi) + - libxml: . Fixed custom external entity loader returning an invalid resource leading to a confusing TypeError message. (Girgias) From 90f582b1880e7ff09f083dfd326e82a8730ee9fd Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 10 Apr 2025 17:21:15 +0200 Subject: [PATCH 312/503] [ci skip] fix news --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 416d97aeee93f..6e91f46dc6b18 100644 --- a/NEWS +++ b/NEWS @@ -9,7 +9,7 @@ PHP NEWS (David Carlier) - LDAP: - . Fixed bug GH-17940 (LDAP_OPT_X_TLS_REQUIRE_CERT can't be overridden). (Remi) + . Fixed bug GH-17776 (LDAP_OPT_X_TLS_* options can't be overridden). (Remi) - libxml: . Fixed custom external entity loader returning an invalid resource leading From 94681850a12812a8e2ba31333d918bf9ee89482b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 10 Apr 2025 17:21:50 +0200 Subject: [PATCH 313/503] [ci skip] fix news --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8f165880aa8fa..50ea67eb7f519 100644 --- a/NEWS +++ b/NEWS @@ -20,7 +20,7 @@ PHP NEWS (David Carlier) - LDAP: - . Fixed bug GH-17940 (LDAP_OPT_X_TLS_REQUIRE_CERT can't be overridden). (Remi) + . Fixed bug GH-17776 (LDAP_OPT_X_TLS_* options can't be overridden). (Remi) - libxml: . Fixed custom external entity loader returning an invalid resource leading From 10b2754056ce624ea0eab58674b8673a5dba3040 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Thu, 10 Apr 2025 12:04:50 -0700 Subject: [PATCH 314/503] UPGRADING: fix typos and duplicated words --- UPGRADING | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADING b/UPGRADING index 3d69637d51797..89a8fc83b35b7 100644 --- a/UPGRADING +++ b/UPGRADING @@ -188,8 +188,8 @@ PHP 8.5 UPGRADE NOTES default. - FPM: - . FPM with httpd ProxyPass decodes the full scirpt path script path. Added - fastcgi.script_path_encoded INI setting to prevent this new behevior. + . FPM with httpd ProxyPass decodes the full script path. Added + fastcgi.script_path_encoded INI setting to prevent this new behavior. ======================================== 4. Deprecated Functionality From c927d24af69e43c0955faf6f634b83068bdb7b2a Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Fri, 11 Apr 2025 12:39:31 +0900 Subject: [PATCH 315/503] ext/bcmath: Use `const` qualifiers appropriately (#18284) --- ext/bcmath/bcmath.c | 4 ++-- ext/bcmath/libbcmath/src/compare.c | 6 ++---- ext/bcmath/libbcmath/src/div.c | 6 +++--- ext/bcmath/libbcmath/src/doaddsub.c | 12 ++++++------ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 962f839ba83f4..1e0e6d14d81eb 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -1164,7 +1164,7 @@ static zend_always_inline bcmath_number_obj_t *bcmath_number_new_obj(bc_num ret, return intern; } -static zend_result bcmath_number_parse_num(zval *zv, zend_object **obj, zend_string **str, zend_long *lval) +static zend_result bcmath_number_parse_num(const zval *zv, zend_object **obj, zend_string **str, zend_long *lval) { if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), bcmath_number_ce)) { *obj = Z_OBJ_P(zv); @@ -1372,7 +1372,7 @@ static int bcmath_number_compare(zval *op1, zval *op2) } static zend_always_inline zend_result bc_num_from_obj_or_str_or_long_with_err( - bc_num *num, size_t *scale, zend_object *obj, zend_string *str, zend_long lval, uint32_t arg_num) + bc_num *num, size_t *scale, const zend_object *obj, const zend_string *str, zend_long lval, uint32_t arg_num) { size_t full_scale = 0; if (UNEXPECTED(bc_num_from_obj_or_str_or_long(num, &full_scale, obj, str, lval) == FAILURE)) { diff --git a/ext/bcmath/libbcmath/src/compare.c b/ext/bcmath/libbcmath/src/compare.c index 2c24dab777059..06ef246782089 100644 --- a/ext/bcmath/libbcmath/src/compare.c +++ b/ext/bcmath/libbcmath/src/compare.c @@ -41,8 +41,6 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool use_sign) { - char *n1ptr, *n2ptr; - /* First, compare signs. */ if (use_sign && n1->n_sign != n2->n_sign) { /* @@ -91,8 +89,8 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool us /* If we get here, they have the same number of integer digits. check the integer part and the equal length part of the fraction. */ size_t count = n1->n_len + MIN (n1_scale, n2_scale); - n1ptr = n1->n_value; - n2ptr = n2->n_value; + const char *n1ptr = n1->n_value; + const char *n2ptr = n2->n_value; while ((count > 0) && (*n1ptr == *n2ptr)) { n1ptr++; diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 1cf8a434c8608..24ec9a64d77fc 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -70,7 +70,7 @@ static inline void bc_fast_div( */ static inline void bc_standard_div( BC_VECTOR *numerator_vectors, size_t numerator_arr_size, - BC_VECTOR *divisor_vectors, size_t divisor_arr_size, size_t divisor_len, + const BC_VECTOR *divisor_vectors, size_t divisor_arr_size, size_t divisor_len, BC_VECTOR *quot_vectors, size_t quot_arr_size ) { size_t numerator_top_index = numerator_arr_size - 1; @@ -354,10 +354,10 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) return true; } - char *numeratorptr = numerator->n_value; + const char *numeratorptr = numerator->n_value; size_t numerator_size = numerator->n_len + quot_scale + divisor->n_scale; - char *divisorptr = divisor->n_value; + const char *divisorptr = divisor->n_value; size_t divisor_size = divisor->n_len + divisor->n_scale; /* check and remove numerator leading zeros */ diff --git a/ext/bcmath/libbcmath/src/doaddsub.c b/ext/bcmath/libbcmath/src/doaddsub.c index feb50120c70c3..f516f2bda72df 100644 --- a/ext/bcmath/libbcmath/src/doaddsub.c +++ b/ext/bcmath/libbcmath/src/doaddsub.c @@ -46,7 +46,7 @@ bc_num _bc_do_add(bc_num n1, bc_num n2) size_t min_len = MIN (n1->n_len, n2->n_len); size_t min_scale = MIN(n1->n_scale, n2->n_scale); size_t min_bytes = min_len + min_scale; - char *n1ptr, *n2ptr, *sumptr; + char *sumptr; bool carry = 0; size_t count; @@ -54,8 +54,8 @@ bc_num _bc_do_add(bc_num n1, bc_num n2) sum = bc_new_num_nonzeroed(sum_len, sum_scale); /* Start with the fraction part. Initialize the pointers. */ - n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale - 1); - n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale - 1); + const char *n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale - 1); + const char *n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale - 1); sumptr = (char *) (sum->n_value + sum_scale + sum_len - 1); /* Add the fraction part. First copy the longer fraction.*/ @@ -182,14 +182,14 @@ bc_num _bc_do_sub(bc_num n1, bc_num n2) size_t borrow = 0; size_t count; int val; - char *n1ptr, *n2ptr, *diffptr; + char *diffptr; /* Allocate temporary storage. */ diff = bc_new_num_nonzeroed(diff_len, diff_scale); /* Initialize the subtract. */ - n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale - 1); - n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale - 1); + const char *n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale - 1); + const char *n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale - 1); diffptr = (char *) (diff->n_value + diff_len + diff_scale - 1); /* Take care of the longer scaled number. */ From 2f6c0692964f6602be0ae1f2474a1c348a315f3f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 11 Apr 2025 17:53:43 +0200 Subject: [PATCH 316/503] Implement GH-18261: Allow cast to be used in constant expressions (#18264) --- NEWS | 1 + UPGRADING | 1 + .../constexpr/constant_expressions_cast.phpt | 64 ++++++ ...tant_expressions_cast_object_property.phpt | 10 + Zend/zend_ast.c | 35 ++++ Zend/zend_compile.c | 7 + Zend/zend_execute.h | 54 +++++ Zend/zend_vm_def.h | 48 +---- Zend/zend_vm_execute.h | 192 +----------------- 9 files changed, 182 insertions(+), 230 deletions(-) create mode 100644 Zend/tests/constexpr/constant_expressions_cast.phpt create mode 100644 Zend/tests/constexpr/constant_expressions_cast_object_property.phpt diff --git a/NEWS b/NEWS index c37cec11fda0f..67b42c4788d93 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,7 @@ PHP NEWS (timwolla, Volker Dusch) . Added get_error_handler(), get_exception_handler() functions. (Arnaud) . Fixed bug GH-15753 and GH-16198 (Bind traits before parent class). (ilutov) + . Added support for casts in constant expressions. (nielsdos) - Curl: . Added curl_multi_get_handles(). (timwolla) diff --git a/UPGRADING b/UPGRADING index 89a8fc83b35b7..34e4f48bd2fb1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -130,6 +130,7 @@ PHP 8.5 UPGRADE NOTES RFC: https://wiki.php.net/rfc/marking_return_value_as_important . Added asymmetric visibility support for static properties. RFC: https://wiki.php.net/rfc/static-aviz + . Added support for casts in constant expressions. - Curl: . Added support for share handles that are persisted across multiple PHP diff --git a/Zend/tests/constexpr/constant_expressions_cast.phpt b/Zend/tests/constexpr/constant_expressions_cast.phpt new file mode 100644 index 0000000000000..4431e2c08d6b0 --- /dev/null +++ b/Zend/tests/constexpr/constant_expressions_cast.phpt @@ -0,0 +1,64 @@ +--TEST-- +Constant expressions with cast +--FILE-- + 1]; +const T5 = (float) 5; +const T6 = (array) ""; +const T7 = (array) var_dump(...); +const T8 = (array) new X; +const T9 = (array) new DateTime; +const T10 = (int) new DateTime; + +var_dump(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); +?> +--EXPECTF-- +Warning: Array to string conversion in %s on line %d + +Warning: Object of class DateTime could not be converted to int in %s on line %d +int(0) +bool(true) +string(5) "Array" +object(stdClass)#%d (1) { + ["a"]=> + int(1) +} +float(5) +array(1) { + [0]=> + string(0) "" +} +array(1) { + [0]=> + object(Closure)#%d (2) { + ["function"]=> + string(8) "var_dump" + ["parameter"]=> + array(2) { + ["$value"]=> + string(10) "" + ["$values"]=> + string(10) "" + } + } +} +array(1) { + ["foo"]=> + int(3) +} +array(3) { + ["date"]=> + string(%d) "%s" + ["timezone_type"]=> + int(%d) + ["timezone"]=> + string(%d) "%s" +} +int(1) diff --git a/Zend/tests/constexpr/constant_expressions_cast_object_property.phpt b/Zend/tests/constexpr/constant_expressions_cast_object_property.phpt new file mode 100644 index 0000000000000..63616f0f8bf3b --- /dev/null +++ b/Zend/tests/constexpr/constant_expressions_cast_object_property.phpt @@ -0,0 +1,10 @@ +--TEST-- +Constant expressions with object cast in property +--FILE-- + +--EXPECTF-- +Fatal error: Object casts are not supported in this context in %s on line %d diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 2551f876d4465..991d85ff39ce1 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -702,6 +702,41 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } zval_ptr_dtor_nogc(&op1); break; + case ZEND_AST_CAST: + if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) { + ret = FAILURE; + break; + } + if (ast->attr == Z_TYPE(op1)) { + ZVAL_COPY_VALUE(result, &op1); + } else { + switch (ast->attr) { + case _IS_BOOL: + ZVAL_BOOL(result, zend_is_true(&op1)); + break; + case IS_LONG: + ZVAL_LONG(result, zval_get_long_func(&op1, false)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double_func(&op1)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string_func(&op1)); + break; + case IS_ARRAY: + zend_cast_zval_to_array(result, &op1, IS_VAR); + break; + case IS_OBJECT: + zend_cast_zval_to_object(result, &op1, IS_VAR); + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + zval_ptr_dtor_nogc(&op1); + if (UNEXPECTED(EG(exception))) { + ret = FAILURE; + } + } + break; case ZEND_AST_OR: if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) { ret = FAILURE; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2ad3f6b323d8f..064f7bfbd194f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -11121,6 +11121,7 @@ static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */ || kind == ZEND_AST_AND || kind == ZEND_AST_OR || kind == ZEND_AST_UNARY_OP || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS + || kind == ZEND_AST_CAST || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM || kind == ZEND_AST_UNPACK @@ -11395,6 +11396,12 @@ static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */ case ZEND_AST_MAGIC_CONST: zend_compile_const_expr_magic_const(ast_ptr); break; + case ZEND_AST_CAST: + if (ast->attr == IS_OBJECT && !ctx->allow_dynamic) { + zend_error_noreturn(E_COMPILE_ERROR, + "Object casts are not supported in this context"); + } + break; case ZEND_AST_NEW: if (!ctx->allow_dynamic) { zend_error_noreturn(E_COMPILE_ERROR, diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 97ef66879db91..b9fef311d9f9b 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -219,6 +219,60 @@ static zend_always_inline void zend_safe_assign_to_variable_noref(zval *variable } } +static zend_always_inline void zend_cast_zval_to_object(zval *result, zval *expr, uint8_t op1_type) { + HashTable *ht; + + ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); + if (Z_TYPE_P(expr) == IS_ARRAY) { + ht = zend_symtable_to_proptable(Z_ARR_P(expr)); + if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { + /* TODO: try not to duplicate immutable arrays as well ??? */ + ht = zend_array_dup(ht); + } + Z_OBJ_P(result)->properties = ht; + } else if (Z_TYPE_P(expr) != IS_NULL) { + Z_OBJ_P(result)->properties = ht = zend_new_array(1); + expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); + if (op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } +} + +static zend_always_inline void zend_cast_zval_to_array(zval *result, zval *expr, uint8_t op1_type) { + extern zend_class_entry *zend_ce_closure; + if (op1_type == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { + if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(1)); + expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); + if (op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); + } else { + if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); + } + } else { + ZVAL_EMPTY_ARRAY(result); + } + } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { + /* Optimized version without rebuilding properties HashTable */ + ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); + } else { + HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); + if (obj_ht) { + /* fast copy */ + ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, + (Z_OBJCE_P(expr)->default_properties_count || + Z_OBJ_P(expr)->handlers != &std_object_handlers || + GC_IS_RECURSIVE(obj_ht)))); + zend_release_properties(obj_ht); + } else { + ZVAL_EMPTY_ARRAY(result); + } + } +} + ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9317d1ff592f5..60bb87ecbf741 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6459,7 +6459,6 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE) USE_OPLINE zval *expr; zval *result = EX_VAR(opline->result.var); - HashTable *ht; SAVE_OPLINE(); expr = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -6493,53 +6492,10 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE) } if (opline->extended_value == IS_ARRAY) { - if (OP1_TYPE == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (OP1_TYPE == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } else { - ZVAL_EMPTY_ARRAY(result); - } - } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); - } else { - ZVAL_EMPTY_ARRAY(result); - } - } + zend_cast_zval_to_array(result, expr, OP1_TYPE); } else { ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (OP1_TYPE == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } + zend_cast_zval_to_object(result, expr, OP1_TYPE); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f7bec6f7198c8..d41f37f668115 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5233,7 +5233,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H USE_OPLINE zval *expr; zval *result = EX_VAR(opline->result.var); - HashTable *ht; SAVE_OPLINE(); expr = RT_CONSTANT(opline, opline->op1); @@ -5266,53 +5265,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H } if (opline->extended_value == IS_ARRAY) { - if (IS_CONST == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } else { - ZVAL_EMPTY_ARRAY(result); - } - } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); - } else { - ZVAL_EMPTY_ARRAY(result); - } - } + zend_cast_zval_to_array(result, expr, IS_CONST); } else { ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } + zend_cast_zval_to_object(result, expr, IS_CONST); } } @@ -20154,7 +20110,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC USE_OPLINE zval *expr; zval *result = EX_VAR(opline->result.var); - HashTable *ht; SAVE_OPLINE(); expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); @@ -20187,53 +20142,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC } if (opline->extended_value == IS_ARRAY) { - if (IS_TMP_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } else { - ZVAL_EMPTY_ARRAY(result); - } - } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); - } else { - ZVAL_EMPTY_ARRAY(result); - } - } + zend_cast_zval_to_array(result, expr, IS_TMP_VAR); } else { ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } + zend_cast_zval_to_object(result, expr, IS_TMP_VAR); } } @@ -22820,7 +22732,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC USE_OPLINE zval *expr; zval *result = EX_VAR(opline->result.var); - HashTable *ht; SAVE_OPLINE(); expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -22854,53 +22765,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC } if (opline->extended_value == IS_ARRAY) { - if (IS_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } else { - ZVAL_EMPTY_ARRAY(result); - } - } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); - } else { - ZVAL_EMPTY_ARRAY(result); - } - } + zend_cast_zval_to_array(result, expr, IS_VAR); } else { ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } + zend_cast_zval_to_object(result, expr, IS_VAR); } } @@ -41061,7 +40929,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO USE_OPLINE zval *expr; zval *result = EX_VAR(opline->result.var); - HashTable *ht; SAVE_OPLINE(); expr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -41094,53 +40961,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO } if (opline->extended_value == IS_ARRAY) { - if (IS_CV == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { - if (Z_TYPE_P(expr) != IS_NULL) { - ZVAL_ARR(result, zend_new_array(1)); - expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } else { - ZVAL_EMPTY_ARRAY(result); - } - } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) { - /* Optimized version without rebuilding properties HashTable */ - ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr))); - } else { - HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST); - if (obj_ht) { - /* fast copy */ - ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht, - (Z_OBJCE_P(expr)->default_properties_count || - Z_OBJ_P(expr)->handlers != &std_object_handlers || - GC_IS_RECURSIVE(obj_ht)))); - zend_release_properties(obj_ht); - } else { - ZVAL_EMPTY_ARRAY(result); - } - } + zend_cast_zval_to_array(result, expr, IS_CV); } else { ZEND_ASSERT(opline->extended_value == IS_OBJECT); - ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); - if (Z_TYPE_P(expr) == IS_ARRAY) { - ht = zend_symtable_to_proptable(Z_ARR_P(expr)); - if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - /* TODO: try not to duplicate immutable arrays as well ??? */ - ht = zend_array_dup(ht); - } - Z_OBJ_P(result)->properties = ht; - } else if (Z_TYPE_P(expr) != IS_NULL) { - Z_OBJ_P(result)->properties = ht = zend_new_array(1); - expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); - } else { - if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); - } - } + zend_cast_zval_to_object(result, expr, IS_CV); } } From 4a12a9f3e9866ce34bc29348614d6cc5e907b4e6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 10 Apr 2025 20:11:02 +0200 Subject: [PATCH 317/503] Fix GH-18294: assertion failure zend_jit_ir.c The JIT helper `zend_jit_assign_op_to_typed_ref` expects a `zval*` as an argument, so we have to store to the stack if OP1_DATA(=op3) is in a register. Closes GH-18299. --- NEWS | 3 +++ ext/opcache/jit/zend_jit_ir.c | 7 ++++++ ext/opcache/tests/jit/gh18294.phpt | 37 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 ext/opcache/tests/jit/gh18294.phpt diff --git a/NEWS b/NEWS index 50ea67eb7f519..b110830629160 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,9 @@ PHP NEWS . Fixed custom external entity loader returning an invalid resource leading to a confusing TypeError message. (Girgias) +- Opcache: + . Fixed bug GH-18294 (assertion failure zend_jit_ir.c). (nielsdos) + - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. (nielsdos) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 7ff6522ba2c4a..e9b1a9f01e184 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -13482,6 +13482,13 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, ref_path = ir_END(); ir_IF_TRUE_cold(if_typed); + if (Z_MODE(op3_addr) == IS_REG) { + zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var); + if (!zend_jit_spill_store_inv(jit, op3_addr, real_addr, op1_data_info)) { + return 0; + } + op3_addr = real_addr; + } arg2 = jit_ZVAL_ADDR(jit, op3_addr); ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_op_to_typed_ref), reference, arg2, ir_CONST_FC_FUNC(binary_op)); diff --git a/ext/opcache/tests/jit/gh18294.phpt b/ext/opcache/tests/jit/gh18294.phpt new file mode 100644 index 0000000000000..a3e99e8e7bf0c --- /dev/null +++ b/ext/opcache/tests/jit/gh18294.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-18294 (assertion failure zend_jit_ir.c) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1152 +opcache.jit_hot_func=1 +opcache.jit_hot_side_exit=1 +--FILE-- +>= $overflow; + } + } + return $fusion; +} +?> +--EXPECT-- +Array +( + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 0 + [7] => 0 + [8] => 0 +) From 14853ea2f2b102bd71b633bd63fec0aa870dfe27 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 10 Apr 2025 20:11:56 +0200 Subject: [PATCH 318/503] Fix reproducibility of test GH-17190 The test failure did not trigger for me when playing with the JIT code. From the original issue report some INI settings were not set properly. --- ext/opcache/tests/jit/gh17190.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/opcache/tests/jit/gh17190.phpt b/ext/opcache/tests/jit/gh17190.phpt index d4bb4372b9215..9027050ed6897 100644 --- a/ext/opcache/tests/jit/gh17190.phpt +++ b/ext/opcache/tests/jit/gh17190.phpt @@ -7,7 +7,9 @@ opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 opcache.jit_buffer_size=32M -opcache.jit=function +opcache.jit=1254 +opcache.jit_hot_func=1 +opcache.jit_hot_side_exit=1 --FILE-- Date: Sat, 29 Mar 2025 23:42:45 +0100 Subject: [PATCH 319/503] Fix potential leaks when writing to BIO fails When the BIO is created but writing fails, these can leak. Closes GH-18186. --- NEWS | 1 + ext/openssl/openssl.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 6e91f46dc6b18..045d9c8d9f431 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ PHP NEWS - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. (nielsdos) + . Fix potential leaks when writing to BIO fails. (nielsdos) - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index bfbf51ff6442c..c978859b7ec00 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5742,8 +5742,8 @@ PHP_FUNCTION(openssl_pkcs7_read) BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); - BIO_free(bio_out); } + BIO_free(bio_out); } } @@ -5757,8 +5757,8 @@ PHP_FUNCTION(openssl_pkcs7_read) BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); - BIO_free(bio_out); } + BIO_free(bio_out); } } @@ -6383,8 +6383,8 @@ PHP_FUNCTION(openssl_cms_read) BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); - BIO_free(bio_out); } + BIO_free(bio_out); } } @@ -6398,8 +6398,8 @@ PHP_FUNCTION(openssl_cms_read) BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); - BIO_free(bio_out); } + BIO_free(bio_out); } } From ba0853888d8735b1d46fbe26ca7254327b1423aa Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:18:14 +0200 Subject: [PATCH 320/503] Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault For dynamic fetches the cache_slot will be NULL, so we have to check for that when resetting the cache. For zip and xmlreader this couldn't easily be tested because of a lack of writable properties. Closes GH-18307. --- NEWS | 4 ++++ ext/date/php_date.c | 4 +++- ext/date/tests/gh18304.phpt | 35 ++++++++++++++++++++++++++++++++ ext/dom/php_dom.c | 4 +++- ext/dom/tests/gh18304.phpt | 15 ++++++++++++++ ext/pdo/pdo_stmt.c | 5 +++-- ext/simplexml/simplexml.c | 4 +++- ext/simplexml/tests/gh18304.phpt | 18 ++++++++++++++++ ext/snmp/snmp.c | 4 +++- ext/snmp/tests/gh18304.phpt | 15 ++++++++++++++ ext/spl/spl_array.c | 4 +++- ext/spl/tests/gh18304.phpt | 14 +++++++++++++ ext/xmlreader/php_xmlreader.c | 4 ++-- ext/zip/php_zip.c | 4 ++-- 14 files changed, 123 insertions(+), 11 deletions(-) create mode 100644 ext/date/tests/gh18304.phpt create mode 100644 ext/dom/tests/gh18304.phpt create mode 100644 ext/simplexml/tests/gh18304.phpt create mode 100644 ext/snmp/tests/gh18304.phpt create mode 100644 ext/spl/tests/gh18304.phpt diff --git a/NEWS b/NEWS index 045d9c8d9f431..64911472be3b3 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.21 +- Core: + . Fixed bug GH-18304 (Changing the properties of a DateInterval through + dynamic properties triggers a SegFault). (nielsdos) + - GD: . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage in gdImageCrop(). (David Carlier) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 6f7796eec1250..c1faa842f8a12 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4399,7 +4399,9 @@ static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string zend_string_equals_literal(name, "days") || zend_string_equals_literal(name, "invert") ) { /* Fallback to read_property. */ - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } ret = NULL; } else { ret = zend_std_get_property_ptr_ptr(object, name, type, cache_slot); diff --git a/ext/date/tests/gh18304.phpt b/ext/date/tests/gh18304.phpt new file mode 100644 index 0000000000000..4bab058a7ec4a --- /dev/null +++ b/ext/date/tests/gh18304.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault) +--CREDITS-- +orose-assetgo +--FILE-- +$field += $i; +var_dump($di); +?> +--EXPECT-- +object(DateInterval)#1 (10) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) +} diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 1da53bae64b51..841dcd66186f8 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -303,7 +303,9 @@ static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, in return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } return NULL; } diff --git a/ext/dom/tests/gh18304.phpt b/ext/dom/tests/gh18304.phpt new file mode 100644 index 0000000000000..ead44306ff801 --- /dev/null +++ b/ext/dom/tests/gh18304.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault) +--CREDITS-- +orose-assetgo +--EXTENSIONS-- +dom +--FILE-- +$field .= 'hello'; +var_dump($text->$field); +?> +--EXPECT-- +string(5) "hello" diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index efbf519e5411e..8454b4875374e 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2493,9 +2493,10 @@ static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name ZEND_IGNORE_VALUE(object); ZEND_IGNORE_VALUE(name); ZEND_IGNORE_VALUE(type); - ZEND_IGNORE_VALUE(cache_slot); - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } return NULL; } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 46ec3a2a788ab..11f497a6673ea 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -635,7 +635,9 @@ static zval *sxe_property_get_adr(zend_object *object, zend_string *zname, int f SXE_ITER type; zval member; - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } sxe = php_sxe_fetch_object(object); GET_NODE(sxe, node); diff --git a/ext/simplexml/tests/gh18304.phpt b/ext/simplexml/tests/gh18304.phpt new file mode 100644 index 0000000000000..b92690856e231 --- /dev/null +++ b/ext/simplexml/tests/gh18304.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault) +--CREDITS-- +orose-assetgo +--EXTENSIONS-- +simplexml +--FILE-- +'); +$field = 'abc'; +$sxe->$field .= 'hello'; +var_dump($sxe->$field); +?> +--EXPECT-- +object(SimpleXMLElement)#3 (1) { + [0]=> + string(5) "hello" +} diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 02348a5fbca00..0ba39ed87c241 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1861,7 +1861,9 @@ static zval *php_snmp_get_property_ptr_ptr(zend_object *object, zend_string *nam return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } return NULL; } diff --git a/ext/snmp/tests/gh18304.phpt b/ext/snmp/tests/gh18304.phpt new file mode 100644 index 0000000000000..2faf503ac1a58 --- /dev/null +++ b/ext/snmp/tests/gh18304.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault) +--CREDITS-- +orose-assetgo +--EXTENSIONS-- +snmp +--FILE-- +$field++; +var_dump($snmp->$field); +?> +--EXPECT-- +int(1) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 8d4541797a1c5..0abaf743ac9d1 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -846,7 +846,9 @@ static zval *spl_array_get_property_ptr_ptr(zend_object *object, zend_string *na if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 && !zend_std_has_property(object, name, ZEND_PROPERTY_EXISTS, NULL)) { - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; + } /* If object has offsetGet() overridden, then fallback to read_property, * which will call offsetGet(). */ diff --git a/ext/spl/tests/gh18304.phpt b/ext/spl/tests/gh18304.phpt new file mode 100644 index 0000000000000..d93ee3534d0d4 --- /dev/null +++ b/ext/spl/tests/gh18304.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault) +--CREDITS-- +orose-assetgo +--FILE-- + 1]); +$ao->setFlags(ArrayObject::ARRAY_AS_PROPS); +$field = 'abc'; +$ao->$field++; +var_dump($ao->$field); +?> +--EXPECT-- +int(2) diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index 569058e91a454..dca1898f1c044 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -121,8 +121,6 @@ zval *xmlreader_get_property_ptr_ptr(zend_object *object, zend_string *name, int zval *retval = NULL; xmlreader_prop_handler *hnd = NULL; - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; - obj = php_xmlreader_fetch_object(object); if (obj->prop_handler != NULL) { @@ -131,6 +129,8 @@ zval *xmlreader_get_property_ptr_ptr(zend_object *object, zend_string *name, int if (hnd == NULL) { retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot); + } else if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; } return retval; diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index e28cf688dcff8..172057685105b 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -890,8 +890,6 @@ static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name zval *retval = NULL; zip_prop_handler *hnd = NULL; - cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; - obj = php_zip_fetch_object(object); if (obj->prop_handler != NULL) { @@ -900,6 +898,8 @@ static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name if (hnd == NULL) { retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot); + } else if (cache_slot) { + cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL; } return retval; From 8849a5336ea6feda910567acca34407901d3fc57 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 11 Apr 2025 20:59:34 +0200 Subject: [PATCH 321/503] Fix GH-18309: ipv6 filter integer overflow The intermediate computation can cause a signed integer overflow, but the input is correctly rejected later on by the check on variable `n`. Solve this by using an unsigned number. Closes GH-18312. --- NEWS | 3 +++ ext/filter/logical_filters.c | 3 ++- ext/filter/tests/gh18309.phpt | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 ext/filter/tests/gh18309.phpt diff --git a/NEWS b/NEWS index 64911472be3b3..c652b3b83744a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ PHP NEWS . Fixed bug GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault). (nielsdos) +- Filter: + . Fixed bug GH-18309 (ipv6 filter integer overflow). (nielsdos) + - GD: . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage in gdImageCrop(). (David Carlier) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 1bd9bad5afbe1..76656a218d281 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -762,7 +762,8 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) { int compressed_pos = -1; int blocks = 0; - int num, n, i; + unsigned int num, n; + int i; char *ipv4; const char *end; int ip4elm[4]; diff --git a/ext/filter/tests/gh18309.phpt b/ext/filter/tests/gh18309.phpt new file mode 100644 index 0000000000000..b541f10883fe6 --- /dev/null +++ b/ext/filter/tests/gh18309.phpt @@ -0,0 +1,10 @@ +--TEST-- +GH-18309 (ipv6 filter integer overflow) +--EXTENSIONS-- +filter +--FILE-- + +--EXPECT-- +bool(false) From c5edf94003309812a2189c407bf8a1513db08618 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 22:39:11 +0100 Subject: [PATCH 322/503] ext/gmp: Use zend_result type instead of int type --- ext/gmp/gmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index f38ffef17aa32..80c767181d50e 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -514,7 +514,7 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch mpz_ptr gmpnum; const unsigned char *p, *max; zval *zv; - int retval = FAILURE; + zend_result retval = FAILURE; php_unserialize_data_t unserialize_data; zend_object *zobj; From 7415dc4649ea057cc2e800aec1dde535b12cd550 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 11 Apr 2025 23:56:57 +0200 Subject: [PATCH 323/503] Fix sxe test --- ext/simplexml/tests/gh18304.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/simplexml/tests/gh18304.phpt b/ext/simplexml/tests/gh18304.phpt index b92690856e231..c6b0f76bd04e2 100644 --- a/ext/simplexml/tests/gh18304.phpt +++ b/ext/simplexml/tests/gh18304.phpt @@ -11,8 +11,8 @@ $field = 'abc'; $sxe->$field .= 'hello'; var_dump($sxe->$field); ?> ---EXPECT-- -object(SimpleXMLElement)#3 (1) { +--EXPECTF-- +object(SimpleXMLElement)#%d (1) { [0]=> string(5) "hello" } From 1684c52a88d1429cf19d4927fe2edf7ff37c66be Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 12 Apr 2025 09:59:56 +0200 Subject: [PATCH 324/503] Fix GlobIterator without constructor breaks count() (#18314) As reported by OpenAI AARDVARK. --- ext/spl/spl_directory.c | 12 ++++++------ ext/spl/tests/GlobIterator_constructor_count.phpt | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 ext/spl/tests/GlobIterator_constructor_count.phpt diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 461bdc1e901ec..751000fe63004 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1599,12 +1599,12 @@ PHP_METHOD(GlobIterator, count) RETURN_THROWS(); } - /* The spl_filesystem_object_get_method_check() function is called prior to calling this function. - * Therefore, the directory entry cannot be NULL. However, if it is not NULL, then it must be a glob iterator - * by construction. */ - ZEND_ASSERT(spl_intern_is_glob(intern)); - - RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL)); + if (EXPECTED(spl_intern_is_glob(intern))) { + RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL)); + } else { + /* This can happen by avoiding constructors in specially-crafted code. */ + zend_throw_error(NULL, "GlobIterator is not initialized"); + } } /* }}} */ #endif /* HAVE_GLOB */ diff --git a/ext/spl/tests/GlobIterator_constructor_count.phpt b/ext/spl/tests/GlobIterator_constructor_count.phpt new file mode 100644 index 0000000000000..5f96be6219d62 --- /dev/null +++ b/ext/spl/tests/GlobIterator_constructor_count.phpt @@ -0,0 +1,14 @@ +--TEST-- +GlobIterator without constructor breaks count() +--FILE-- +newInstanceWithoutConstructor(); +try { + count($in); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +GlobIterator is not initialized From c8b33289960dd95f049e0a6bf8e25303abde2a2c Mon Sep 17 00:00:00 2001 From: Carlos Buenosvinos Date: Sun, 13 Apr 2025 07:29:33 -0700 Subject: [PATCH 325/503] [skip ci] 8.2 branch is security fixes only (GH-18319) Based on the explanation on https://www.php.net/supported-versions.php, 8.2 moved into security fixes only on 31 Dec 2024. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9f34c239c55e..e5b2e91d63d1b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -353,7 +353,7 @@ Currently, we have the following branches in use: | master | Active development branch for PHP 8.5, which is open for backwards incompatible changes and major internal API changes. | | PHP-8.4 | Is used to release the PHP 8.4.x series. This is a current stable version and is open for bugfixes only. | | PHP-8.3 | Is used to release the PHP 8.3.x series. This is a current stable version and is open for bugfixes only. | -| PHP-8.2 | Is used to release the PHP 8.2.x series. This is a current stable version and is open for bugfixes only. | +| PHP-8.2 | Is used to release the PHP 8.2.x series. This is an old stable version and is open for security fixes only. | | PHP-8.1 | Is used to release the PHP 8.1.x series. This is an old stable version and is open for security fixes only. | | PHP-8.0 | This branch is closed. | | PHP-7.4 | This branch is closed. | From ef180f1623122f1a2f4ea9a9e0284cec543a5e6b Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 23:02:30 +0100 Subject: [PATCH 326/503] ext/iconv: Reduce scope of variables --- ext/iconv/iconv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index b61d253c5d4be..fb3741f0dd892 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -298,17 +298,18 @@ static php_output_handler *php_iconv_output_handler_init(const char *handler_nam static zend_result php_iconv_output_handler(void **nothing, php_output_context *output_context) { - char *s, *content_type, *mimetype = NULL; - int output_status, mimetype_len = 0; + char *content_type, *mimetype = NULL; if (output_context->op & PHP_OUTPUT_HANDLER_START) { - output_status = php_output_get_status(); + int output_status = php_output_get_status(); if (output_status & PHP_OUTPUT_SENT) { return FAILURE; } + int mimetype_len = 0; if (SG(sapi_headers).mimetype && !strncasecmp(SG(sapi_headers).mimetype, "text/", 5)) { - if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){ + char *s = strchr(SG(sapi_headers).mimetype,';'); + if (s == NULL){ mimetype = SG(sapi_headers).mimetype; } else { mimetype = SG(sapi_headers).mimetype; @@ -775,7 +776,6 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval, size_t match_ofs; int more; - size_t iconv_ret; *pretval = (size_t)-1; @@ -812,7 +812,7 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval, more = in_left > 0; - iconv_ret = iconv(cd, more ? (ICONV_CONST char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); + size_t iconv_ret = iconv(cd, more ? (ICONV_CONST char **)&in_p : NULL, more ? &in_left : NULL, (char **) &out_p, &out_left); if (out_left == sizeof(buf)) { break; } From bba44fc3fec964730b17bd449e060d5a306573ae Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 22:59:59 +0100 Subject: [PATCH 327/503] ext/iconv: Add const specifier --- ext/iconv/iconv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index fb3741f0dd892..641a0517dad0d 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -63,15 +63,15 @@ #define PHP_ICONV_IMPL_VALUE "unknown" #endif -static char *get_iconv_version(void) { - char *version = "unknown"; +static const char *get_iconv_version(void) { + const char *version = "unknown"; #ifdef HAVE_LIBICONV static char buf[16]; snprintf(buf, sizeof(buf), "%d.%d", _libiconv_version >> 8, _libiconv_version & 0xff); version = buf; #elif defined(HAVE_GLIBC_ICONV) - version = (char *) gnu_get_libc_version(); + version = gnu_get_libc_version(); #endif return version; @@ -243,7 +243,7 @@ PHP_MSHUTDOWN_FUNCTION(miconv) /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(miconv) { - zval *iconv_impl, *iconv_ver; + const zval *iconv_impl, *iconv_ver; iconv_impl = zend_get_constant_str("ICONV_IMPL", sizeof("ICONV_IMPL")-1); iconv_ver = zend_get_constant_str("ICONV_VERSION", sizeof("ICONV_VERSION")-1); @@ -308,7 +308,7 @@ static zend_result php_iconv_output_handler(void **nothing, php_output_context * int mimetype_len = 0; if (SG(sapi_headers).mimetype && !strncasecmp(SG(sapi_headers).mimetype, "text/", 5)) { - char *s = strchr(SG(sapi_headers).mimetype,';'); + const char *s = strchr(SG(sapi_headers).mimetype,';'); if (s == NULL){ mimetype = SG(sapi_headers).mimetype; } else { @@ -321,7 +321,7 @@ static zend_result php_iconv_output_handler(void **nothing, php_output_context * if (mimetype != NULL && (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || ((output_context->op & PHP_OUTPUT_HANDLER_START) && !(output_context->op & PHP_OUTPUT_HANDLER_FINAL)))) { size_t len; - char *p = strstr(get_output_encoding(), "//"); + const char *p = strstr(get_output_encoding(), "//"); if (p) { len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, (int) (p - get_output_encoding()), get_output_encoding()); @@ -2577,7 +2577,7 @@ static php_stream_filter *php_iconv_stream_filter_factory_create(const char *nam { php_stream_filter *retval = NULL; php_iconv_stream_filter *inst; - char *from_charset = NULL, *to_charset = NULL; + const char *from_charset = NULL, *to_charset = NULL; size_t from_charset_len, to_charset_len; if ((from_charset = strchr(name, '.')) == NULL) { From 2d3db4b59473161af268642c3124d6c6e3520fb3 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 23:05:42 +0100 Subject: [PATCH 328/503] ext/iconv: Use bool type instead of int type --- ext/iconv/iconv.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 641a0517dad0d..6119fe8c3a336 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -418,16 +418,16 @@ static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd /* {{{ */ #ifdef ICONV_BROKEN_IGNORE -static int _php_check_ignore(const char *charset) +static bool _php_check_ignore(const char *charset) { size_t clen = strlen(charset); if (clen >= 9 && strcmp("//IGNORE", charset+clen-8) == 0) { - return 1; + return true; } if (clen >= 19 && strcmp("//IGNORE//TRANSLIT", charset+clen-18) == 0) { - return 1; + return true; } - return 0; + return false; } #else #define _php_check_ignore(x) (0) @@ -443,7 +443,7 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, size_t bsz, result = 0; php_iconv_err_t retval = PHP_ICONV_ERR_SUCCESS; zend_string *out_buf; - int ignore_ilseq = _php_check_ignore(out_charset); + bool ignore_ilseq = _php_check_ignore(out_charset); *out = NULL; @@ -560,7 +560,7 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_ size_t out_left; size_t cnt; - int more; + bool more; *pretval = (size_t)-1; @@ -637,7 +637,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval, size_t cnt; size_t total_len; - int more; + bool more; err = _php_iconv_strlen(&total_len, str, nbytes, enc); if (err != PHP_ICONV_ERR_SUCCESS) { @@ -775,7 +775,7 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval, size_t ndl_buf_left; size_t match_ofs; - int more; + bool more; *pretval = (size_t)-1; From e1686aabf776f18faecbda19d808edac406721f7 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 23:09:17 +0100 Subject: [PATCH 329/503] ext/iconv: Hardcode 0 for PHP_ICONV_ERR_SUCCESS value Instead of relying on the zend_result SUCCESS value which doesn't have much to do with it here. --- ext/iconv/php_iconv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/iconv/php_iconv.h b/ext/iconv/php_iconv.h index 7bc1cce0df9f5..fcabdfaf6449e 100644 --- a/ext/iconv/php_iconv.h +++ b/ext/iconv/php_iconv.h @@ -67,7 +67,7 @@ ZEND_TSRMLS_CACHE_EXTERN() /* {{{ typedef enum php_iconv_err_t */ typedef enum _php_iconv_err_t { - PHP_ICONV_ERR_SUCCESS = SUCCESS, + PHP_ICONV_ERR_SUCCESS = 0, PHP_ICONV_ERR_CONVERTER = 1, PHP_ICONV_ERR_WRONG_CHARSET = 2, PHP_ICONV_ERR_TOO_BIG = 3, From 4eb8839037c4e87d7878882328da6fd1561606be Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 11 Apr 2025 23:36:36 +0100 Subject: [PATCH 330/503] ext/iconv: Use RETURN_BOOL() instead of if/else --- ext/iconv/iconv.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 6119fe8c3a336..157ee41a11a05 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -2255,11 +2255,7 @@ PHP_FUNCTION(iconv_set_encoding) retval = zend_alter_ini_entry(name, charset, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); zend_string_release_ex(name, 0); - if (retval == SUCCESS) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(retval == SUCCESS); } /* }}} */ From a142f10aa113c67cd478b3ef054963c84480a7a7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:19:14 +0200 Subject: [PATCH 331/503] Don't evaluate GMP comparison multiple times (#18321) ZEND_THREEWAY_COMPARE evaluates its operands multiple times. --- ext/gmp/gmp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 80c767181d50e..8cf20c90fc7a2 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -480,7 +480,8 @@ static int gmp_compare(zval *op1, zval *op2) /* {{{ */ return ZEND_UNCOMPARABLE; } - return ZEND_THREEWAY_COMPARE(mpz_cmp(gmp_op1, gmp_op2), 0); + int ret = mpz_cmp(gmp_op1, gmp_op2); /* avoid multiple evaluations */ + return ZEND_THREEWAY_COMPARE(ret, 0); } /* }}} */ @@ -1422,7 +1423,8 @@ ZEND_FUNCTION(gmp_cmp) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_b) ZEND_PARSE_PARAMETERS_END(); - RETURN_LONG(ZEND_THREEWAY_COMPARE(mpz_cmp(gmpnum_a, gmpnum_b), 0)); + int ret = mpz_cmp(gmpnum_a, gmpnum_b); /* avoid multiple evaluations */ + RETURN_LONG(ZEND_THREEWAY_COMPARE(ret, 0)); } /* }}} */ From 67503870ca2957aca9270bad324b32ab349559aa Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:29:08 +0200 Subject: [PATCH 332/503] Fix GH-18322: SplObjectStorage debug handler mismanages memory This hack was once necessary before there was a proper get_gc handler, but now it breaks the engine constraints. Closes GH-18323. --- NEWS | 4 ++++ ext/spl/spl_observer.c | 6 ++---- ext/spl/tests/gh18322.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/gh18322.phpt diff --git a/NEWS b/NEWS index c652b3b83744a..6e5a4bc4cfc62 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ PHP NEWS (nielsdos) . Fix potential leaks when writing to BIO fails. (nielsdos) +- SPL: + . Fixed bug GH-18322 (SplObjectStorage debug handler mismanages memory). + (nielsdos) + - Standard: . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()). (Jakub Zelenka) diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index b3a27cb10292c..83889c430b7a2 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -340,12 +340,10 @@ static inline HashTable* spl_object_storage_debug_info(zend_object *obj) /* {{{ ZEND_HASH_FOREACH_PTR(&intern->storage, element) { array_init(&tmp); - /* Incrementing the refcount of obj and inf would confuse the garbage collector. - * Prefer to null the destructor */ - Z_ARRVAL_P(&tmp)->pDestructor = NULL; zval obj; - ZVAL_OBJ(&obj, element->obj); + ZVAL_OBJ_COPY(&obj, element->obj); add_assoc_zval_ex(&tmp, "obj", sizeof("obj") - 1, &obj); + Z_TRY_ADDREF(element->inf); add_assoc_zval_ex(&tmp, "inf", sizeof("inf") - 1, &element->inf); zend_hash_next_index_insert(Z_ARRVAL(storage), &tmp); } ZEND_HASH_FOREACH_END(); diff --git a/ext/spl/tests/gh18322.phpt b/ext/spl/tests/gh18322.phpt new file mode 100644 index 0000000000000..e70cbd0d37dd5 --- /dev/null +++ b/ext/spl/tests/gh18322.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-18322 (SplObjectStorage debug handler mismanages memory) +--FILE-- +__debugInfo(); +$tmp2 = $tmp[array_key_first($tmp)]; +unset($tmp); // Drop $tmp2 RC to 1 +$tmp2[0]['obj'] = new stdClass; +var_dump($tmp2); + +?> +--EXPECT-- +array(1) { + [0]=> + array(2) { + ["obj"]=> + object(stdClass)#3 (0) { + } + ["inf"]=> + int(1) + } +} From 9ac8820fc94cb1800e561197c074a46170dba107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 14 Apr 2025 15:36:51 +0200 Subject: [PATCH 333/503] =?UTF-8?q?zend=5Fcompile:=20Allow=20`(void)`=20in?= =?UTF-8?q?=20for=E2=80=99s=20initializer=20and=20loop=20expression=20(#18?= =?UTF-8?q?303)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * zend_compile: Allow `(void)` in for’s initializer and loop expression The initializer and loop expression of a `for()` loop only accept expressions, but they act like statements in spirit - their results are completely ignored. Allow `(void)` there to allow suppressing `#[\NoDiscard]`, since there is no semantic ambiguity of what `(void)` returns anyways. Fixes php/php-src#18301 * zend_language_parser: Simplify `for()` grammar --- .../type_casts/gh18301_cast_to_void_for.phpt | 46 +++++++++++++++ ..._cast_to_void_statement_for_condition.phpt | 9 +++ Zend/zend_compile.c | 56 ++++++++++--------- Zend/zend_language_parser.y | 12 +++- 4 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 Zend/tests/type_casts/gh18301_cast_to_void_for.phpt create mode 100644 Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt diff --git a/Zend/tests/type_casts/gh18301_cast_to_void_for.phpt b/Zend/tests/type_casts/gh18301_cast_to_void_for.phpt new file mode 100644 index 0000000000000..2ff7cfb0cb17b --- /dev/null +++ b/Zend/tests/type_casts/gh18301_cast_to_void_for.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-18301: casting to void is allowed in for’s expression lists +--FILE-- + +--EXPECTF-- +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d +4 + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d +10 + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d +16 + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d +22 + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d +28 + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d + +Warning: The return value of function incCount() should either be used or intentionally ignored by casting it as (void) in %s on line %d diff --git a/Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt b/Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt new file mode 100644 index 0000000000000..6c90b2f7987c6 --- /dev/null +++ b/Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt @@ -0,0 +1,9 @@ +--TEST-- +GH-18301: casting to void is not allowed at the end of a for condition +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected token ";", expecting "," in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 064f7bfbd194f..4f18999ffa785 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5717,6 +5717,26 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ } /* }}} */ +static void zend_compile_void_cast(znode *result, zend_ast *ast) +{ + zend_ast *expr_ast = ast->child[0]; + znode expr_node; + zend_op *opline; + + zend_compile_expr(&expr_node, expr_ast); + + switch (expr_node.op_type) { + case IS_TMP_VAR: + case IS_VAR: + opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); + opline->extended_value = ZEND_FREE_VOID_CAST; + break; + case IS_CONST: + zend_do_free(&expr_node); + break; + } +} + static void zend_compile_echo(zend_ast *ast) /* {{{ */ { zend_op *opline; @@ -5967,7 +5987,7 @@ static void zend_compile_do_while(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_for_expr_list(znode *result, zend_ast *ast) /* {{{ */ { zend_ast_list *list; uint32_t i; @@ -5984,7 +6004,13 @@ static void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */ zend_ast *expr_ast = list->child[i]; zend_do_free(result); - zend_compile_expr(result, expr_ast); + if (expr_ast->kind == ZEND_AST_CAST_VOID) { + zend_compile_void_cast(NULL, expr_ast); + result->op_type = IS_CONST; + ZVAL_NULL(&result->u.constant); + } else { + zend_compile_expr(result, expr_ast); + } } } /* }}} */ @@ -5999,7 +6025,7 @@ static void zend_compile_for(zend_ast *ast) /* {{{ */ znode result; uint32_t opnum_start, opnum_jmp, opnum_loop; - zend_compile_expr_list(&result, init_ast); + zend_compile_for_expr_list(&result, init_ast); zend_do_free(&result); opnum_jmp = zend_emit_jump(0); @@ -6010,11 +6036,11 @@ static void zend_compile_for(zend_ast *ast) /* {{{ */ zend_compile_stmt(stmt_ast); opnum_loop = get_next_op_number(); - zend_compile_expr_list(&result, loop_ast); + zend_compile_for_expr_list(&result, loop_ast); zend_do_free(&result); zend_update_jump_target_to_next(opnum_jmp); - zend_compile_expr_list(&result, cond_ast); + zend_compile_for_expr_list(&result, cond_ast); zend_do_extended_stmt(); zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start); @@ -10594,26 +10620,6 @@ static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_void_cast(znode *result, zend_ast *ast) -{ - zend_ast *expr_ast = ast->child[0]; - znode expr_node; - zend_op *opline; - - zend_compile_expr(&expr_node, expr_ast); - - switch (expr_node.op_type) { - case IS_TMP_VAR: - case IS_VAR: - opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); - opline->extended_value = ZEND_FREE_VOID_CAST; - break; - case IS_CONST: - zend_do_free(&expr_node); - break; - } -} - static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 9483a83b4e955..190292fada760 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -268,7 +268,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type callable_expr callable_variable static_member new_variable %type encaps_var encaps_var_offset isset_variables %type top_statement_list use_declarations const_list inner_statement_list if_stmt -%type alt_if_stmt for_exprs switch_case_list global_var_list static_var_list +%type alt_if_stmt for_cond_exprs for_exprs switch_case_list global_var_list static_var_list %type echo_expr_list unset_variables catch_name_list catch_list optional_variable parameter_list class_statement_list %type implements_list case_list if_stmt_without_else %type non_empty_parameter_list argument_list non_empty_argument_list property_list @@ -508,7 +508,7 @@ statement: { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); } | T_DO statement T_WHILE '(' expr ')' ';' { $$ = zend_ast_create(ZEND_AST_DO_WHILE, $2, $5); } - | T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement + | T_FOR '(' for_exprs ';' for_cond_exprs ';' for_exprs ')' for_statement { $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); } | T_SWITCH '(' expr ')' switch_case_list { $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); } @@ -1169,6 +1169,12 @@ echo_expr: expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } ; +for_cond_exprs: + %empty { $$ = NULL; } + | non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); } + | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } +; + for_exprs: %empty { $$ = NULL; } | non_empty_for_exprs { $$ = $1; } @@ -1176,6 +1182,8 @@ for_exprs: non_empty_for_exprs: non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); } + | non_empty_for_exprs ',' T_VOID_CAST expr { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_CAST_VOID, $4)); } + | T_VOID_CAST expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, zend_ast_create(ZEND_AST_CAST_VOID, $2)); } | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } ; From 701f3a1af67029a1d953ca054f33385be32c7f4a Mon Sep 17 00:00:00 2001 From: haszi Date: Tue, 9 Jan 2024 14:43:44 +0100 Subject: [PATCH 334/503] Mark ob_start callback parameter nullable --- ext/standard/basic_functions.stub.php | 2 +- ext/standard/basic_functions_arginfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index be9b024258ee8..3bdc3827b4d36 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1513,7 +1513,7 @@ function header_register_callback(callable $callback): bool {} /* main/output.c */ -/** @param callable $callback */ +/** @param callable|null $callback */ function ob_start($callback = null, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): bool {} function ob_flush(): bool {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 99e08feddf590..1361cf6062797 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7389d094a842a2289cd32cb37386e5e40ea7e031 */ + * Stub hash: 2a3d8da0b92134dcca74f2ac70454bd27768f20e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) From 0a10f6db26875e0f1d0f867307cee591d29a43c7 Mon Sep 17 00:00:00 2001 From: hanshenrik Date: Sun, 13 Apr 2025 18:45:51 +0200 Subject: [PATCH 335/503] ext/pdo_sqlite - throw on null bytes / resolve GH-13952 (#18320) fix a corruption issue where PDO::quote for SQLite would silently truncate strings with null bytes in them, by throwing. Fixes #13952 Closes #18320 --- NEWS | 3 ++ UPGRADING | 4 ++ ext/pdo_sqlite/sqlite_driver.c | 15 +++++- ext/pdo_sqlite/tests/gh13952.phpt | 79 +++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_sqlite/tests/gh13952.phpt diff --git a/NEWS b/NEWS index 67b42c4788d93..38af4b7681d20 100644 --- a/NEWS +++ b/NEWS @@ -112,6 +112,9 @@ PHP NEWS Pdo\Pgsql::prepare(…, [ PDO::ATTR_PREFETCH => 0 ]) make fetch() lazy instead of storing the whole result set in memory (Guillaume Outters) +- PDO_SQLITE: + . throw on null bytes / resolve GH-13952 (divinity76). + - PGSQL: . Added pg_close_stmt to close a prepared statement while allowing its name to be reused. (David Carlier) diff --git a/UPGRADING b/UPGRADING index 34e4f48bd2fb1..2b7abad173c74 100644 --- a/UPGRADING +++ b/UPGRADING @@ -222,6 +222,10 @@ PHP 8.5 UPGRADE NOTES PDO::ATTR_PREFETCH sets to 0 which set to lazy fetch mode. In this mode, statements cannot be run parallely. +- PDO_SQLITE: + . SQLite PDO::quote() will now throw an exception or emit a warning, + depending on the error mode, if the string contains a null byte. + - PGSQL: . pg_copy_from also supports inputs as Iterable. . pg_connect checks if the connection_string argument contains diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 645d7bc3333ed..8a880a3425fba 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -226,6 +226,19 @@ static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unqu if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) { return NULL; } + + if (UNEXPECTED(zend_str_has_nul_byte(unquoted))) { + if (dbh->error_mode == PDO_ERRMODE_EXCEPTION) { + zend_throw_exception_ex( + php_pdo_get_exception(), 0, + "SQLite PDO::quote does not support null bytes"); + } else if (dbh->error_mode == PDO_ERRMODE_WARNING) { + php_error_docref(NULL, E_WARNING, + "SQLite PDO::quote does not support null bytes"); + } + return NULL; + } + quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3); /* TODO use %Q format? */ sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted)); @@ -741,7 +754,7 @@ static const struct pdo_dbh_methods sqlite_methods = { pdo_sqlite_request_shutdown, pdo_sqlite_in_transaction, pdo_sqlite_get_gc, - pdo_sqlite_scanner + pdo_sqlite_scanner }; static char *make_filename_safe(const char *filename) diff --git a/ext/pdo_sqlite/tests/gh13952.phpt b/ext/pdo_sqlite/tests/gh13952.phpt new file mode 100644 index 0000000000000..b6a080cfa22a2 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh13952.phpt @@ -0,0 +1,79 @@ +--TEST-- +GH-13952 (sqlite PDO::quote handles null bytes correctly) +--EXTENSIONS-- +pdo +pdo_sqlite +--FILE-- + PDO::ERRMODE_EXCEPTION, + 'warning' => PDO::ERRMODE_WARNING, + 'silent' => PDO::ERRMODE_SILENT, +]; + +$test_cases = [ + "", + "x", + "\x00", + "a\x00b", + "\x00\x00\x00", + "foobar", + "foo'''bar", + "'foo'''bar'", + "foo\x00bar", + "'foo'\x00'bar'", + "foo\x00\x00\x00bar", + "\x00foo\x00\x00\x00bar\x00", + "\x00\x00\x00foo", + "foo\x00\x00\x00", + "\x80", // << invalid UTF-8 + "\x00\x80\x00", // << invalid UTF-8 with null bytes +]; + +foreach ($modes as $mode_name => $mode) { + echo "Testing error mode: $mode_name\n"; + $db = new PDO('sqlite::memory:', null, null, [PDO::ATTR_ERRMODE => $mode]); + + foreach ($test_cases as $test) { + $contains_null = str_contains($test, "\x00"); + + if ($mode === PDO::ERRMODE_EXCEPTION && $contains_null) { + set_error_handler(fn() => throw new PDOException(), E_WARNING); + try { + $db->quote($test); + throw new LogicException("Expected exception not thrown."); + } catch (PDOException) { + // expected + } finally { + restore_error_handler(); + } + } else { + set_error_handler(fn() => null, E_WARNING); + $quoted = $db->quote($test); + restore_error_handler(); + + if ($contains_null) { + if ($quoted !== false) { + throw new LogicException("Expected false, got: " . var_export($quoted, true)); + } + } else { + if ($quoted === false) { + throw new LogicException("Unexpected false from quote()."); + } + $fetched = $db->query("SELECT $quoted")->fetchColumn(); + if ($fetched !== $test) { + throw new LogicException("Data corrupted: expected " . var_export($test, true) . " got " . var_export($fetched, true)); + } + } + } + } +} + +echo "ok\n"; +?> +--EXPECT-- +Testing error mode: exception +Testing error mode: warning +Testing error mode: silent +ok From 9d4f8b5379f2dfb071f4311ed5d0c421e014dbf7 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Tue, 8 Apr 2025 23:32:36 +0900 Subject: [PATCH 336/503] Fixed GH-18276 - persistent connection - "zend_mm_heap corrupted" with setAttribute() (#18280) Closes #18280 Fixes #18276 --- NEWS | 4 ++++ ext/pdo_firebird/firebird_driver.c | 21 +++++++++-------- ext/pdo_firebird/tests/gh18276.phpt | 35 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 ext/pdo_firebird/tests/gh18276.phpt diff --git a/NEWS b/NEWS index 6e5a4bc4cfc62..7d660e26cef75 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ PHP NEWS (nielsdos) . Fix potential leaks when writing to BIO fails. (nielsdos) +- PDO Firebird: + . Fixed GH-18276 - persistent connection - "zend_mm_heap corrupted" + with setAttribute() (SakiTakamachi). + - SPL: . Fixed bug GH-18322 (SplObjectStorage debug handler mismanages memory). (nielsdos) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 4f8cd83d7b8ab..504e739a974d9 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -492,13 +492,13 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ } if (H->date_format) { - efree(H->date_format); + pefree(H->date_format, dbh->is_persistent); } if (H->time_format) { - efree(H->time_format); + pefree(H->time_format, dbh->is_persistent); } if (H->timestamp_format) { - efree(H->timestamp_format); + pefree(H->timestamp_format, dbh->is_persistent); } pefree(H, dbh->is_persistent); @@ -881,9 +881,10 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * return false; } if (H->date_format) { - efree(H->date_format); + pefree(H->date_format, dbh->is_persistent); + H->date_format = NULL; } - spprintf(&H->date_format, 0, "%s", ZSTR_VAL(str)); + H->date_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); zend_string_release_ex(str, 0); } return true; @@ -895,9 +896,10 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * return false; } if (H->time_format) { - efree(H->time_format); + pefree(H->time_format, dbh->is_persistent); + H->time_format = NULL; } - spprintf(&H->time_format, 0, "%s", ZSTR_VAL(str)); + H->time_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); zend_string_release_ex(str, 0); } return true; @@ -909,9 +911,10 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * return false; } if (H->timestamp_format) { - efree(H->timestamp_format); + pefree(H->timestamp_format, dbh->is_persistent); + H->timestamp_format = NULL; } - spprintf(&H->timestamp_format, 0, "%s", ZSTR_VAL(str)); + H->timestamp_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); zend_string_release_ex(str, 0); } return true; diff --git a/ext/pdo_firebird/tests/gh18276.phpt b/ext/pdo_firebird/tests/gh18276.phpt new file mode 100644 index 0000000000000..610876166ccf7 --- /dev/null +++ b/ext/pdo_firebird/tests/gh18276.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-18276 (persistent connection - setAttribute(Pdo\Firebird::ATTR_DATE_FORMAT, ..) results in "zend_mm_heap corrupted") +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--XLEAK-- +A bug in firebird causes a memory leak when calling `isc_attach_database()`. +See https://github.com/FirebirdSQL/firebird/issues/7849 +--FILE-- + true, + ], + ); + // Avoid interned + $dbh->setAttribute(PDO::FB_ATTR_DATE_FORMAT, str_repeat('Y----m----d', random_int(1, 1))); + $dbh->setAttribute(PDO::FB_ATTR_TIME_FORMAT, str_repeat('H::::i::::s', random_int(1, 1))); + $dbh->setAttribute(PDO::FB_ATTR_TIMESTAMP_FORMAT, str_repeat('Y----m----d....H::::i::::s', random_int(1, 1))); + unset($dbh); +} + +echo 'done!'; +?> +--EXPECT-- +done! From 0f5372dbaa03c0749c1bb233a5c40fe6a74fd3cd Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 11 Apr 2025 16:03:46 +0900 Subject: [PATCH 337/503] followup in master for #18280 (#18302) Closes #18302 --- ext/pdo_firebird/firebird_driver.c | 42 +++++++++++-------------- ext/pdo_firebird/firebird_statement.c | 10 +++--- ext/pdo_firebird/php_pdo_firebird_int.h | 6 ++-- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 6c2de01c85af6..40289719ce9e8 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -599,13 +599,13 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ } if (H->date_format) { - zend_string_release_ex(H->date_format, false); + pefree(H->date_format, dbh->is_persistent); } if (H->time_format) { - zend_string_release_ex(H->time_format, false); + pefree(H->time_format, dbh->is_persistent); } if (H->timestamp_format) { - zend_string_release_ex(H->timestamp_format, false); + pefree(H->timestamp_format, dbh->is_persistent); } if (H->einfo.errmsg) { @@ -1091,9 +1091,11 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->date_format) { - zend_string_release_ex(H->date_format, false); + pefree(H->date_format, dbh->is_persistent); + H->date_format = NULL; } - H->date_format = str; + H->date_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); + zend_string_release_ex(str, 0); } return true; @@ -1104,9 +1106,11 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->time_format) { - zend_string_release_ex(H->time_format, false); + pefree(H->time_format, dbh->is_persistent); + H->time_format = NULL; } - H->time_format = str; + H->time_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); + zend_string_release_ex(str, 0); } return true; @@ -1117,9 +1121,11 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->timestamp_format) { - zend_string_release_ex(H->timestamp_format, false); + pefree(H->timestamp_format, dbh->is_persistent); + H->timestamp_format = NULL; } - H->timestamp_format = str; + H->timestamp_format = pestrndup(ZSTR_VAL(str), ZSTR_LEN(str),dbh->is_persistent); + zend_string_release_ex(str, 0); } return true; @@ -1240,27 +1246,15 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) return 1; case PDO_FB_ATTR_DATE_FORMAT: - if (H->date_format) { - ZVAL_STR_COPY(val, H->date_format); - } else { - ZVAL_STRING(val, PDO_FB_DEF_DATE_FMT); - } + ZVAL_STRING(val, H->date_format ? H->date_format : PDO_FB_DEF_DATE_FMT); return 1; case PDO_FB_ATTR_TIME_FORMAT: - if (H->time_format) { - ZVAL_STR_COPY(val, H->time_format); - } else { - ZVAL_STRING(val, PDO_FB_DEF_TIME_FMT); - } + ZVAL_STRING(val, H->time_format ? H->time_format : PDO_FB_DEF_TIME_FMT); return 1; case PDO_FB_ATTR_TIMESTAMP_FORMAT: - if (H->timestamp_format) { - ZVAL_STR_COPY(val, H->timestamp_format); - } else { - ZVAL_STRING(val, PDO_FB_DEF_TIMESTAMP_FMT); - } + ZVAL_STRING(val, H->timestamp_format ? H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT); return 1; case PDO_FB_TRANSACTION_ISOLATION_LEVEL: diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 4310269314ce0..60a5e60e11bde 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -93,7 +93,7 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv } time = fb_encode_time(hours, minutes, seconds, fractions); isc_decode_sql_time(&time, &t); - fmt = S->H->time_format ? ZSTR_VAL(S->H->time_format) : PDO_FB_DEF_TIME_FMT; + fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT; size_t len = strftime(timeBuf, sizeof(timeBuf), fmt, &t); if (len == 0) { @@ -123,7 +123,7 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* ts.timestamp_time = fb_encode_time(hours, minutes, seconds, fractions); isc_decode_timestamp(&ts, &t); - fmt = S->H->timestamp_format ? ZSTR_VAL(S->H->timestamp_format) : PDO_FB_DEF_TIMESTAMP_FMT; + fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT; size_t len = strftime(timestampBuf, sizeof(timestampBuf), fmt, &t); if (len == 0) { @@ -546,18 +546,18 @@ static int pdo_firebird_stmt_get_col( break; case SQL_TYPE_DATE: isc_decode_sql_date((ISC_DATE*)var->sqldata, &t); - fmt = S->H->date_format ? ZSTR_VAL(S->H->date_format) : PDO_FB_DEF_DATE_FMT; + fmt = S->H->date_format ? S->H->date_format : PDO_FB_DEF_DATE_FMT; if (0) { case SQL_TYPE_TIME: isc_decode_sql_time((ISC_TIME*)var->sqldata, &t); - fmt = S->H->time_format ? ZSTR_VAL(S->H->time_format) : PDO_FB_DEF_TIME_FMT; + fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT; } else if (0) { case SQL_TIMESTAMP: { ISC_TIMESTAMP timestamp = php_get_isc_timestamp_from_sqldata(var->sqldata); isc_decode_timestamp(×tamp, &t); } - fmt = S->H->timestamp_format ? ZSTR_VAL(S->H->timestamp_format) : PDO_FB_DEF_TIMESTAMP_FMT; + fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT; } /* convert the timestamp into a string */ char buf[80]; diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index 1d58be1c4b717..a62c152ffab3e 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -73,9 +73,9 @@ typedef struct { zend_ulong txn_isolation_level; /* date and time format strings, can be set by the set_attribute method */ - zend_string *date_format; - zend_string *time_format; - zend_string *timestamp_format; + char *date_format; + char *time_format; + char *timestamp_format; unsigned sql_dialect:2; From 16c4c066f4d395e4e7bcac4be94e40bbabe4ff9c Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 14 Apr 2025 15:49:26 +0200 Subject: [PATCH 338/503] Make empty_fcall_info and empty_fcall_info_cache macros See https://github.com/php/php-src/pull/18273, a constant may cause unnecessary cache misses. Closes GH-18326 --- Zend/zend_API.h | 11 ++++++++--- Zend/zend_execute_API.c | 4 ---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 6aeffce25d8e5..a644de8e15134 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -690,8 +690,13 @@ ZEND_API zend_result _call_user_function_impl(zval *object, zval *function_name, #define call_user_function_named(function_table, object, function_name, retval_ptr, param_count, params, named_params) \ _call_user_function_impl(object, function_name, retval_ptr, param_count, params, named_params) -ZEND_API extern const zend_fcall_info empty_fcall_info; -ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache; +#ifndef __cplusplus +# define empty_fcall_info (zend_fcall_info) {0} +# define empty_fcall_info_cache (zend_fcall_info_cache) {0} +#else +# define empty_fcall_info zend_fcall_info {0} +# define empty_fcall_info_cache zend_fcall_info_cache {0} +#endif /** Build zend_call_info/cache from a zval* * @@ -800,7 +805,7 @@ static zend_always_inline void zend_fcc_dtor(zend_fcall_info_cache *fcc) if (fcc->closure) { OBJ_RELEASE(fcc->closure); } - memcpy(fcc, &empty_fcall_info_cache, sizeof(zend_fcall_info_cache)); + *fcc = empty_fcall_info_cache; } ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, zval *callable); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1f55521fb72f1..12df2a9ee5b99 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -53,10 +53,6 @@ ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data); ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value); ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name); -/* true globals */ -ZEND_API const zend_fcall_info empty_fcall_info = {0}; -ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = {0}; - #ifdef ZEND_WIN32 ZEND_TLS HANDLE tq_timer = NULL; #endif From b24addddb4ac81316a8bc4b598f1564d77e0c30a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:02:08 +0200 Subject: [PATCH 339/503] run-tests.php: Save STDIN section into a file (#18305) When a test has an --STDIN-- or --PHPDBG-- section, save the section's content into a file, like we do for the other sections. This makes it bit easier to reproduce these tests outside of run-tests.php. This doesn't update the .sh file to pass the file as stdin to the program, yet. When using gdb, we can pass the file as stdin like this: gdb --args php (gdb) r test.php < test.stdin --- .gitignore | 1 + run-tests.php | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index 91120a5fa6b2f..55c441323cf15 100644 --- a/.gitignore +++ b/.gitignore @@ -237,6 +237,7 @@ php **/tests/**/*.exp **/tests/**/*.log **/tests/**/*.sh +**/tests/**/*.stdin # Generated by some test cases **/tests/**/*.db diff --git a/run-tests.php b/run-tests.php index 0db6937c7a848..a90681c7ff7f1 100755 --- a/run-tests.php +++ b/run-tests.php @@ -1934,6 +1934,7 @@ function run_test(string $php, $file, array $env): string $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'diff'; $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'log'; $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'exp'; + $stdin_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'stdin'; $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'out'; $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'mem'; $sh_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'sh'; @@ -1972,6 +1973,7 @@ function run_test(string $php, $file, array $env): string @unlink($diff_filename); @unlink($log_filename); @unlink($exp_filename); + @unlink($stdin_filename); @unlink($output_filename); @unlink($memcheck_filename); @unlink($sh_filename); @@ -2696,6 +2698,16 @@ function run_test(string $php, $file, array $env): string $diff = generate_diff($wanted, $wanted_re, $output); } + // write .stdin + if ($test->hasSection('STDIN') || $test->hasSection('PHPDBG')) { + $stdin = $test->hasSection('STDIN') + ? $test->getSection('STDIN') + : $test->getSection('PHPDBG') . "\n"; + if (file_put_contents($stdin_filename, $stdin) === false) { + error("Cannot create test stdin - $stdin_filename"); + } + } + if (is_array($IN_REDIRECT)) { $orig_shortname = str_replace(TEST_PHP_SRCDIR . '/', '', $file); $diff = "# original source file: $orig_shortname\n" . $diff; From 061b46e09d9485f134427b55d3efb2e257bd6d97 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 9 Apr 2025 16:31:48 +0200 Subject: [PATCH 340/503] Save opline in zend_jit_hot_func() Closes GH-18289 --- NEWS | 1 + ext/opcache/jit/zend_jit.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 5912cde4fa66a..582efbc598c6a 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,7 @@ PHP NEWS - Opcache: . Fixed bug GH-18294 (assertion failure zend_jit_ir.c). (nielsdos) + . Fixed bug GH-18289 (Fix segfault in JIT). (Florian Engelhardt) - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 2d4ef0bf4fc38..e477cbdb5628b 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3033,6 +3033,10 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend op_array->opcodes[i].handler = jit_extension->orig_handlers[i]; } +#ifdef HAVE_GCC_GLOBAL_REGS + EX(opline) = opline; +#endif + /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, opline, ZEND_JIT_ON_HOT_COUNTERS); } zend_catch { From 76d7c616bb8775520f18456b41121bf934cac391 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Feb 2025 15:39:29 +0100 Subject: [PATCH 341/503] Pass opline as argument to opcode handlers in CALL VM This changes the signature of opcode handlers in the CALL VM so that the opline is passed directly via arguments. This reduces the number of memory operations on EX(opline), and makes the CALL VM considerably faster. Additionally, this unifies the CALL and HYBRID VMs a bit, as EX(opline) is now handled in the same way in both VMs. This is a part of GH-17849. Currently we have two VMs: * HYBRID: Used when compiling with GCC. execute_data and opline are global register variables * CALL: Used when compiling with something else. execute_data is passed as opcode handler arg, but opline is passed via execute_data->opline (EX(opline)). The Call VM looks like this: while (1) { ret = execute_data->opline->handler(execute_data); if (UNEXPECTED(ret != 0)) { if (ret > 0) { // returned by ZEND_VM_ENTER() / ZEND_VM_LEAVE() execute_data = EG(current_execute_data); } else { // returned by ZEND_VM_RETURN() return; } } } // example op handler int ZEND_INIT_FCALL_SPEC_CONST_HANDLER(zend_execute_data *execute_data) { // load opline const zend_op *opline = execute_data->opline; // instruction execution // dispatch // ZEND_VM_NEXT_OPCODE(): execute_data->opline++; return 0; // ZEND_VM_CONTINUE() } Opcode handlers return a positive value to signal that the loop must load a new execute_data from EG(current_execute_data), typically when entering or leaving a function. Here I make the following changes: * Pass opline as opcode handler argument * Return next opline from opcode handlers * ZEND_VM_ENTER / ZEND_VM_LEAVE return opline|(1<<0) to signal that execute_data must be reloaded from EG(current_execute_data) This gives us: while (1) { opline = opline->handler(execute_data, opline); if (UNEXPECTED((uintptr_t) opline & ZEND_VM_ENTER_BIT) { opline = opline & ~ZEND_VM_ENTER_BIT; if (opline != 0) { // ZEND_VM_ENTER() / ZEND_VM_LEAVE() execute_data = EG(current_execute_data); } else { // ZEND_VM_RETURN() return; } } } // example op handler const zend_op * ZEND_INIT_FCALL_SPEC_CONST_HANDLER(zend_execute_data *execute_data, const zend_op *opline) { // opline already loaded // instruction execution // dispatch // ZEND_VM_NEXT_OPCODE(): return ++opline; } bench.php is 23% faster on Linux / x86_64, 18% faster on MacOS / M1. Symfony Demo is 2.8% faster. When using the HYBRID VM, JIT'ed code stores execute_data/opline in two fixed callee-saved registers and rarely touches EX(opline), just like the VM. Since the registers are callee-saved, the JIT'ed code doesn't have to save them before calling other functions, and can assume they always contain execute_data/opline. The code also avoids saving/restoring them in prologue/epilogue, as execute_ex takes care of that (JIT'ed code is called exclusively from there). The CALL VM can now use a fixed register for execute_data/opline as well, but we can't rely on execute_ex to save the registers for us as it may use these registers itself. So we have to save/restore the two registers in JIT'ed code prologue/epilogue. Closes GH-17952 --- Zend/zend_vm_def.h | 3 +- Zend/zend_vm_execute.h | 372 ++++++++++++++------------ Zend/zend_vm_execute.skl | 2 + Zend/zend_vm_gen.php | 92 ++++--- Zend/zend_vm_opcodes.h | 2 + ext/opcache/jit/zend_jit.c | 27 +- ext/opcache/jit/zend_jit_internal.h | 38 +-- ext/opcache/jit/zend_jit_ir.c | 292 +++++++++----------- ext/opcache/jit/zend_jit_trace.c | 7 +- ext/opcache/jit/zend_jit_vm_helpers.c | 99 +++---- sapi/phpdbg/tests/watch_006.phpt | 4 +- 11 files changed, 457 insertions(+), 481 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 60bb87ecbf741..7b861688c9661 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5656,11 +5656,10 @@ ZEND_VM_HOT_HANDLER(199, ZEND_CHECK_UNDEF_ARGS, UNUSED, UNUSED) ZEND_VM_COLD_HELPER(zend_missing_arg_helper, ANY, ANY) { -#ifdef ZEND_VM_IP_GLOBAL_REG USE_OPLINE SAVE_OPLINE(); -#endif + zend_missing_arg_error(execute_data); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d41f37f668115..43df17b4b80b8 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -306,6 +306,8 @@ static uint8_t zend_user_opcodes[256] = {0, 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; +#include "Zend/zend_vm_opcodes.h" + #define SPEC_START_MASK 0x0000ffff #define SPEC_EXTRA_MASK 0xfffc0000 #define SPEC_RULE_OP1 0x00010000 @@ -367,13 +369,13 @@ static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op #ifdef ZEND_VM_FP_GLOBAL_REG # define ZEND_OPCODE_HANDLER_ARGS void # define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU -# define ZEND_OPCODE_HANDLER_ARGS_DC -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC +# define ZEND_OPCODE_HANDLER_ARGS_EX +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX #else -# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data -# define ZEND_OPCODE_HANDLER_ARGS_DC , ZEND_OPCODE_HANDLER_ARGS -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC , ZEND_OPCODE_HANDLER_ARGS_PASSTHRU +# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data, const zend_op *opline +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data, opline +# define ZEND_OPCODE_HANDLER_ARGS_EX ZEND_OPCODE_HANDLER_ARGS, +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, #endif #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) @@ -394,18 +396,18 @@ static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op # define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE # endif #else -# define ZEND_OPCODE_HANDLER_RET int +# define ZEND_OPCODE_HANDLER_RET const zend_op * # define ZEND_VM_TAIL_CALL(call) return call -# define ZEND_VM_CONTINUE() return 0 -# define ZEND_VM_RETURN() return -1 +# define ZEND_VM_CONTINUE() return opline +# define ZEND_VM_RETURN() return (const zend_op*)ZEND_VM_ENTER_BIT # define ZEND_VM_HOT # define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE #endif typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); -#define DCL_OPLINE #ifdef ZEND_VM_IP_GLOBAL_REG +# define DCL_OPLINE # define OPLINE opline # define USE_OPLINE # define LOAD_OPLINE() opline = EX(opline) @@ -414,12 +416,13 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H # define SAVE_OPLINE() EX(opline) = opline # define SAVE_OPLINE_EX() SAVE_OPLINE() #else -# define OPLINE EX(opline) -# define USE_OPLINE const zend_op *opline = EX(opline); -# define LOAD_OPLINE() -# define LOAD_OPLINE_EX() -# define LOAD_NEXT_OPLINE() ZEND_VM_INC_OPCODE() -# define SAVE_OPLINE() +# define DCL_OPLINE const zend_op *opline; +# define OPLINE opline +# define USE_OPLINE +# define LOAD_OPLINE() opline = EX(opline) +# define LOAD_OPLINE_EX() opline = EX(opline) +# define LOAD_NEXT_OPLINE() opline = EX(opline) + 1 +# define SAVE_OPLINE() EX(opline) = opline # define SAVE_OPLINE_EX() #endif #define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE() @@ -433,9 +436,10 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H # define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX() # define ZEND_VM_LEAVE() return 2 #else -# define ZEND_VM_ENTER_EX() return 1 -# define ZEND_VM_ENTER() return 1 -# define ZEND_VM_LEAVE() return 2 +# define ZEND_VM_ENTER_BIT 1ULL +# define ZEND_VM_ENTER_EX() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT) +# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX() +# define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT) #endif #define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); #define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -444,7 +448,7 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_add_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -465,7 +469,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_add_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_sub_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -486,7 +490,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_sub_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mul_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -517,7 +521,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mo HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -538,7 +542,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_left_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -559,7 +563,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_left_h ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -580,7 +584,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -602,7 +606,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel ZEND_VM_SMART_BRANCH(ret == 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -624,7 +628,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal ZEND_VM_SMART_BRANCH(ret != 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -646,7 +650,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h ZEND_VM_SMART_BRANCH(ret < 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -668,7 +672,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o ZEND_VM_SMART_BRANCH(ret <= 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -689,7 +693,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_and_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -710,7 +714,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_and_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -731,7 +735,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_not_helper_SPEC(zval *op_1 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) { USE_OPLINE @@ -876,7 +880,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_SPEC(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *prop; @@ -913,19 +917,19 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -941,13 +945,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) @@ -2365,7 +2369,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( } } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_cannot_pass_by_ref_helper_SPEC(uint32_t _arg_num, zval *_arg ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t _arg_num, zval *_arg) { USE_OPLINE @@ -2743,16 +2747,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { -#ifdef ZEND_VM_IP_GLOBAL_REG USE_OPLINE SAVE_OPLINE(); -#endif + zend_missing_arg_error(execute_data); HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_arg_type_helper_SPEC(zval *op_1 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) { USE_OPLINE @@ -2776,7 +2779,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_NOTYPE_SPEC_H ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -3256,7 +3259,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NOP_SPEC_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_helper_SPEC(uint32_t try_catch_offset, uint32_t op_num ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t try_catch_offset, uint32_t op_num) { /* May be NULL during generator closing (only finally blocks are executed) */ zend_object *ex = EG(exception); @@ -3339,7 +3342,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(-1, 0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); } uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; @@ -3403,7 +3406,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( } } - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(current_try_catch_offset, throw_op_num ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, throw_op_num)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3502,7 +3505,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC Z_OBJ_P(fast_call) = NULL; current_try_catch_offset = opline->op2.num; current_op_num = opline - EX(func)->op_array.opcodes; - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(current_try_catch_offset, current_op_num ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -4266,7 +4269,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H param = EX_VAR(opline->result.var); if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { - ZEND_VM_TAIL_CALL(zend_verify_recv_arg_type_helper_SPEC(param ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX param)); } ZEND_VM_NEXT_OPCODE(); @@ -4460,7 +4463,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(op1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6112,7 +6115,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -6154,7 +6157,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6192,7 +6195,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6233,7 +6236,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6274,7 +6277,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6295,7 +6298,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CON ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6314,7 +6317,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CON ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6416,7 +6419,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CON } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6474,7 +6477,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6517,7 +6520,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_C goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6564,7 +6567,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQU goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6596,7 +6599,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_ ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6614,7 +6617,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6632,7 +6635,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7571,7 +7574,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_H } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -8367,7 +8370,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8405,7 +8408,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8432,7 +8435,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8453,7 +8456,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8472,7 +8475,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8515,7 +8518,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8558,7 +8561,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8601,7 +8604,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8648,7 +8651,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8695,7 +8698,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8742,7 +8745,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -10496,7 +10499,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE ZEND_VM_RETURN(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -10599,17 +10602,17 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -10617,17 +10620,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUS int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ @@ -10903,7 +10906,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_ } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -10940,7 +10943,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_C } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -12995,7 +12998,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(op1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13063,7 +13066,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13101,7 +13104,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13142,7 +13145,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13169,7 +13172,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13190,7 +13193,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13209,7 +13212,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13252,7 +13255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13295,7 +13298,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13338,7 +13341,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13385,7 +13388,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13432,7 +13435,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13479,7 +13482,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13497,7 +13500,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARC ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13515,7 +13518,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13533,7 +13536,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14083,7 +14086,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14121,7 +14124,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14162,7 +14165,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HAN } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14189,7 +14192,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HAN } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14210,7 +14213,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HAND ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14229,7 +14232,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HAND ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14272,7 +14275,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVA goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14315,7 +14318,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14358,7 +14361,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14405,7 +14408,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14452,7 +14455,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14499,7 +14502,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14517,7 +14520,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARC ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14535,7 +14538,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14553,7 +14556,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -15848,7 +15851,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -15906,7 +15909,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -15964,7 +15967,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16022,7 +16025,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16080,7 +16083,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16138,7 +16141,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16862,7 +16865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17341,7 +17344,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17399,7 +17402,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17457,7 +17460,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17515,7 +17518,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17573,7 +17576,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17631,7 +17634,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18327,7 +18330,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18537,7 +18540,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HAN ZEND_VM_SMART_BRANCH(result, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -18640,17 +18643,17 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18658,17 +18661,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNU int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ @@ -19734,7 +19737,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -20708,7 +20711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HAN } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -21567,7 +21570,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HA } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -21604,7 +21607,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_T } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -42091,7 +42094,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -42149,7 +42152,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HA } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -42207,7 +42210,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -42265,7 +42268,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -42323,7 +42326,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -42381,7 +42384,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46044,7 +46047,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46102,7 +46105,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46160,7 +46163,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_ } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46218,7 +46221,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46276,7 +46279,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46334,7 +46337,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -49665,7 +49668,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -49768,17 +49771,17 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -49786,17 +49789,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_ int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(fetch_type ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ @@ -51546,7 +51549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -51604,7 +51607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDL } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -51662,7 +51665,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HAND } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -51720,7 +51723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -51778,7 +51781,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -51836,7 +51839,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_ } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -58496,19 +58499,17 @@ ZEND_API void execute_ex(zend_execute_data *ex) #endif /* ZEND_CHECK_STACK_LIMIT */ while (1) { -#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG) - int ret; -#endif #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) HYBRID_SWITCH() { -#else +#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (UNEXPECTED(!OPLINE)) { #else - if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0)) { -#endif + opline = ((opcode_handler_t)opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) { #endif +#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) HYBRID_CASE(ZEND_ASSIGN_STATIC_PROP_OP_SPEC): VM_TRACE(ZEND_ASSIGN_STATIC_PROP_OP_SPEC) @@ -64103,7 +64104,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_NULL) HYBRID_BREAK(); /* Never reached */ -#else +#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ #ifdef ZEND_VM_FP_GLOBAL_REG execute_data = vm_stack_data.orig_execute_data; # ifdef ZEND_VM_IP_GLOBAL_REG @@ -64111,7 +64112,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) # endif return; #else - if (EXPECTED(ret > 0)) { + opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT); + if (EXPECTED(opline != NULL)) { execute_data = EG(current_execute_data); ZEND_VM_LOOP_INTERRUPT_CHECK(); } else { @@ -64121,7 +64123,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) return; } #endif -#endif +#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ } } @@ -68355,6 +68357,7 @@ ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) opcode_handler_t handler; #endif + DCL_OPLINE; int ret; #ifdef ZEND_VM_IP_GLOBAL_REG const zend_op *orig_opline = opline; @@ -68382,8 +68385,23 @@ ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) ret = -1; } #else - ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - SAVE_OPLINE(); + opline = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) { + opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT); + if (EXPECTED(opline)) { + /* ZEND_VM_ENTER() or ZEND_VM_LEAVE() */ + ret = EG(current_execute_data) != ex ? (int)(EG(current_execute_data)->prev_execute_data != ex) + 1 : 0; + execute_data = EG(current_execute_data); + SAVE_OPLINE(); + } else { + /* ZEND_VM_RETURN() */ + ret = -1; + } + } else { + /* ZEND_VM_CONTINUE() */ + SAVE_OPLINE(); + ret = 0; + } #endif #ifdef ZEND_VM_FP_GLOBAL_REG execute_data = orig_execute_data; diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 717d4ffd3e8af..8c0cd1ba605a0 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -1,3 +1,5 @@ +#include "Zend/zend_vm_opcodes.h" + {%DEFINES%} #if (ZEND_VM_KIND != ZEND_VM_KIND_CALL) && (ZEND_GCC_VERSION >= 4000) && !defined(__clang__) diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index c94cd6b616e43..5a4a31b60b8d3 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -818,7 +818,7 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { if (isset($matches[2])) { // extra args $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2); - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))"; + return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; } return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } @@ -852,7 +852,7 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) { if (isset($matches[2])) { // extra args $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2); - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))"; + return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; } return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } @@ -1164,7 +1164,7 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS)\n"); } else { // Helper with parameter - out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name($param ZEND_OPCODE_HANDLER_ARGS_DC)\n"); + out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS_EX $param)\n"); } break; case ZEND_VM_KIND_SWITCH: @@ -1870,13 +1870,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n"); out($f,"# define ZEND_OPCODE_HANDLER_ARGS void\n"); out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC\n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS_EX\n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX\n"); out($f,"#else\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC , ZEND_OPCODE_HANDLER_ARGS\n"); - out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC , ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data, const zend_op *opline\n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data, opline\n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS_EX ZEND_OPCODE_HANDLER_ARGS, \n"); + out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, \n"); out($f,"#endif\n"); out($f,"\n"); out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); @@ -1902,10 +1902,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n"); } out($f,"#else\n"); - out($f,"# define ZEND_OPCODE_HANDLER_RET int\n"); + out($f,"# define ZEND_OPCODE_HANDLER_RET const zend_op *\n"); out($f,"# define ZEND_VM_TAIL_CALL(call) return call\n"); - out($f,"# define ZEND_VM_CONTINUE() return 0\n"); - out($f,"# define ZEND_VM_RETURN() return -1\n"); + out($f,"# define ZEND_VM_CONTINUE() return opline\n"); + out($f,"# define ZEND_VM_RETURN() return (const zend_op*)ZEND_VM_ENTER_BIT\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"# define ZEND_VM_HOT\n"); } @@ -1914,8 +1914,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"\n"); out($f,"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"\n"); - out($f,"#define DCL_OPLINE\n"); out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n"); + out($f,"# define DCL_OPLINE\n"); out($f,"# define OPLINE opline\n"); out($f,"# define USE_OPLINE\n"); out($f,"# define LOAD_OPLINE() opline = EX(opline)\n"); @@ -1924,12 +1924,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# define SAVE_OPLINE() EX(opline) = opline\n"); out($f,"# define SAVE_OPLINE_EX() SAVE_OPLINE()\n"); out($f,"#else\n"); - out($f,"# define OPLINE EX(opline)\n"); - out($f,"# define USE_OPLINE const zend_op *opline = EX(opline);\n"); - out($f,"# define LOAD_OPLINE()\n"); - out($f,"# define LOAD_OPLINE_EX()\n"); - out($f,"# define LOAD_NEXT_OPLINE() ZEND_VM_INC_OPCODE()\n"); - out($f,"# define SAVE_OPLINE()\n"); + out($f,"# define DCL_OPLINE const zend_op *opline;\n"); + out($f,"# define OPLINE opline\n"); + out($f,"# define USE_OPLINE\n"); + out($f,"# define LOAD_OPLINE() opline = EX(opline)\n"); + out($f,"# define LOAD_OPLINE_EX() opline = EX(opline)\n"); + out($f,"# define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n"); + out($f,"# define SAVE_OPLINE() EX(opline) = opline\n"); out($f,"# define SAVE_OPLINE_EX()\n"); out($f,"#endif\n"); out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); @@ -1943,9 +1944,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n"); out($f,"# define ZEND_VM_LEAVE() return 2\n"); out($f,"#else\n"); - out($f,"# define ZEND_VM_ENTER_EX() return 1\n"); - out($f,"# define ZEND_VM_ENTER() return 1\n"); - out($f,"# define ZEND_VM_LEAVE() return 2\n"); + out($f,"# define ZEND_VM_ENTER_BIT 1ULL\n"); + out($f,"# define ZEND_VM_ENTER_EX() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT)\n"); + out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); + out($f,"# define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT)\n"); out($f,"#endif\n"); out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); @@ -2119,12 +2121,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } break; case "ZEND_VM_CONTINUE_LABEL": - if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) { - // Only SWITCH dispatch method use it - out($f,"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n"); - out($f,$m[1]."\tint ret;".$m[3]."\n"); - out($f,"#endif\n"); - } else if ($kind == ZEND_VM_KIND_SWITCH) { + if ($kind == ZEND_VM_KIND_SWITCH) { // Only SWITCH dispatch method use it out($f,"zend_vm_continue:".$m[3]."\n"); } else { @@ -2143,16 +2140,17 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) case ZEND_VM_KIND_HYBRID: out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); out($f, $m[1]."HYBRID_SWITCH()".$m[3]."\n"); - out($f,"#else\n"); + out($f,"#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n"); case ZEND_VM_KIND_CALL: out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); out($f, $m[1]."if (UNEXPECTED(!OPLINE))".$m[3]."\n"); out($f,"#else\n"); - out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3]."\n"); + out($f, $m[1]."opline = ((opcode_handler_t)opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, $m[1]."if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT)))".$m[3]."\n"); out($f,"#endif\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#endif\n"); + out($f,"#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n"); } break; } @@ -2168,7 +2166,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) { // Executor is defined as a set of functions if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#else\n"); + out($f,"#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n"); } out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n" . @@ -2178,18 +2176,19 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) "# endif\n" . $m[1]."return;\n" . "#else\n" . - $m[1]."if (EXPECTED(ret > 0)) {\n" . + $m[1]."opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT);\n". + $m[1]."if (EXPECTED(opline != NULL)) {\n" . $m[1]."\texecute_data = EG(current_execute_data);\n". $m[1]."\tZEND_VM_LOOP_INTERRUPT_CHECK();\n". $m[1]."} else {\n" . "# ifdef ZEND_VM_IP_GLOBAL_REG\n" . $m[1]."\topline = vm_stack_data.orig_opline;\n" . - "# endif\n". + "# endif\n" . $m[1]."\treturn;\n". $m[1]."}\n". "#endif\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#endif\n"); + out($f,"#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n"); } } break; @@ -2335,6 +2334,8 @@ function gen_vm_opcodes_header( ): string { $str = HEADER_TEXT; $str .= "#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n"; + $str .= "#include \"Zend/zend_portability.h\"\n"; + $str .= "\n"; $str .= "#define ZEND_VM_SPEC\t\t" . ZEND_VM_SPEC . "\n"; $str .= "#define ZEND_VM_LINES\t\t" . ZEND_VM_LINES . "\n"; $str .= "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n"; @@ -2968,6 +2969,7 @@ function gen_vm($def, $skel) { out($f, "\topcode_handler_t handler;\n"); out($f,"#endif\n"); } + out($f, "\tDCL_OPLINE;\n"); out($f, "\tint ret;\n"); out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n"); out($f, "\tconst zend_op *orig_opline = opline;\n"); @@ -3001,8 +3003,24 @@ function gen_vm($def, $skel) { out($f, "\t\tret = -1;\n"); out($f, "\t}\n"); out($f, "#else\n"); - out($f, "\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); - out($f, "\tSAVE_OPLINE();\n"); + out($f, "\topline = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + + out($f, "if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) {\n"); + out($f, "\t\topline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT);\n"); + out($f, "\t\tif (EXPECTED(opline)) {\n"); + out($f, "\t\t\t/* ZEND_VM_ENTER() or ZEND_VM_LEAVE() */\n"); + out($f, "\t\t\tret = EG(current_execute_data) != ex ? (int)(EG(current_execute_data)->prev_execute_data != ex) + 1 : 0;\n"); + out($f, "\t\t\texecute_data = EG(current_execute_data);\n"); + out($f, "\t\t\tSAVE_OPLINE();\n"); + out($f, "\t\t} else {\n"); + out($f, "\t\t\t/* ZEND_VM_RETURN() */\n"); + out($f, "\t\t\tret = -1;\n"); + out($f, "\t\t}\n"); + out($f, "\t} else {\n"); + out($f, "\t\t/* ZEND_VM_CONTINUE() */\n"); + out($f, "\t\tSAVE_OPLINE();\n"); + out($f, "\t\tret = 0;\n"); + out($f, "\t}\n"); out($f, "#endif\n"); out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n"); out($f, "\texecute_data = orig_execute_data;\n"); diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index d472b5b9660f5..e15b1a19d5cdb 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -21,6 +21,8 @@ #ifndef ZEND_VM_OPCODES_H #define ZEND_VM_OPCODES_H +#include "Zend/zend_portability.h" + #define ZEND_VM_SPEC 1 #define ZEND_VM_LINES 0 #define ZEND_VM_KIND_CALL 1 diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 0b30045741ee4..355178d9d51ed 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -98,7 +98,7 @@ static const void *zend_jit_func_trace_counter_handler = NULL; static const void *zend_jit_ret_trace_counter_handler = NULL; static const void *zend_jit_loop_trace_counter_handler = NULL; -static int ZEND_FASTCALL zend_runtime_jit(void); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS); static int zend_jit_trace_op_len(const zend_op *opline); static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op *opline); @@ -2871,7 +2871,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(1)); /* ZEND_VM_ENTER */ + zend_jit_vm_enter(jit, jit_IP(jit)); } ir_IF_TRUE(if_hook_enter); } @@ -3074,11 +3074,18 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons } /* Run-time JIT handler */ -static int ZEND_FASTCALL zend_runtime_jit(void) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) { - zend_execute_data *execute_data = EG(current_execute_data); +#if GCC_GLOBAL_REGS + zend_execute_data *execute_data; + zend_op *opline; +#else + const zend_op *orig_opline = opline; +#endif + + execute_data = EG(current_execute_data); zend_op_array *op_array = &EX(func)->op_array; - zend_op *opline = op_array->opcodes; + opline = op_array->opcodes; zend_jit_op_array_extension *jit_extension; bool do_bailout = 0; @@ -3097,7 +3104,7 @@ static int ZEND_FASTCALL zend_runtime_jit(void) } } jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); - opline->handler = jit_extension->orig_handler; + ((zend_op*)opline)->handler = jit_extension->orig_handler; /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, NULL, ZEND_JIT_ON_FIRST_EXEC); @@ -3116,7 +3123,11 @@ static int ZEND_FASTCALL zend_runtime_jit(void) } /* JIT-ed code is going to be called by VM */ - return 0; +#if GCC_GLOBAL_REGS + return; // ZEND_VM_CONTINUE +#else + return orig_opline; // ZEND_VM_CONTINUE +#endif } void zend_jit_check_funcs(HashTable *function_table, bool is_method) { @@ -3171,9 +3182,7 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend op_array->opcodes[i].handler = jit_extension->orig_handlers[i]; } -#ifdef HAVE_GCC_GLOBAL_REGS EX(opline) = opline; -#endif /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, opline, ZEND_JIT_ON_HOT_COUNTERS); diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index b1511c5c1c4df..3ec8ae6041a53 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -21,6 +21,12 @@ #ifndef ZEND_JIT_INTERNAL_H #define ZEND_JIT_INTERNAL_H +#include "Zend/zend_types.h" +#include "Zend/zend_compile.h" +#include "Zend/zend_constants.h" +#include "Zend/Optimizer/zend_func_info.h" +#include "Zend/Optimizer/zend_call_graph.h" + /* Address Encoding */ typedef uintptr_t zend_jit_addr; @@ -183,17 +189,18 @@ extern const zend_op *zend_jit_halt_op; # define ZEND_OPCODE_HANDLER_RET void # define ZEND_OPCODE_HANDLER_ARGS EXECUTE_DATA_D # define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU -# define ZEND_OPCODE_HANDLER_ARGS_DC -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC +# define ZEND_OPCODE_HANDLER_ARGS_EX +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX # define ZEND_OPCODE_RETURN() return # define ZEND_OPCODE_TAIL_CALL(handler) do { \ handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ return; \ } while(0) # define ZEND_OPCODE_TAIL_CALL_EX(handler, arg) do { \ - handler(arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC); \ + handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg); \ return; \ } while(0) +# define ZEND_VM_ENTER_BIT 0 #else # define EXECUTE_DATA_D zend_execute_data* execute_data # define EXECUTE_DATA_C execute_data @@ -203,35 +210,36 @@ extern const zend_op *zend_jit_halt_op; # define OPLINE_C opline # define OPLINE_DC , OPLINE_D # define OPLINE_CC , OPLINE_C -# define ZEND_OPCODE_HANDLER_RET int -# define ZEND_OPCODE_HANDLER_ARGS EXECUTE_DATA_D -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU EXECUTE_DATA_C -# define ZEND_OPCODE_HANDLER_ARGS_DC EXECUTE_DATA_DC -# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC EXECUTE_DATA_CC -# define ZEND_OPCODE_RETURN() return 0 +# define ZEND_OPCODE_HANDLER_RET const zend_op * +# define ZEND_OPCODE_HANDLER_ARGS EXECUTE_DATA_D OPLINE_DC +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU EXECUTE_DATA_C OPLINE_CC +# define ZEND_OPCODE_HANDLER_ARGS_EX EXECUTE_DATA_D OPLINE_DC, +# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX EXECUTE_DATA_C OPLINE_CC, +# define ZEND_OPCODE_RETURN() return opline # define ZEND_OPCODE_TAIL_CALL(handler) do { \ return handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ } while(0) # define ZEND_OPCODE_TAIL_CALL_EX(handler, arg) do { \ - return handler(arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC); \ + return handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg); \ } while(0) +# define ZEND_VM_ENTER_BIT 1ULL #endif /* VM handlers */ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *zend_vm_opcode_handler_t)(ZEND_OPCODE_HANDLER_ARGS); /* VM helpers */ -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(uint32_t call_info EXECUTE_DATA_DC); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(uint32_t call_info EXECUTE_DATA_DC); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(EXECUTE_DATA_D); +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info); +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info); +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(ZEND_OPCODE_HANDLER_ARGS); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_HANDLER_ARGS); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS); -void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D); -void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D); +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper(ZEND_OPCODE_HANDLER_ARGS); +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(ZEND_OPCODE_HANDLER_ARGS); bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D); bool ZEND_FASTCALL zend_jit_nodiscard_helper(OPLINE_D); bool ZEND_FASTCALL zend_jit_deprecated_nodiscard_helper(OPLINE_D); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 2b53724b1d359..60fcdff8a61f3 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -911,18 +911,9 @@ static ir_ref jit_IP32(zend_jit_ctx *jit) return ir_RLOAD_U32(ZREG_IP); } -static void jit_LOAD_IP(zend_jit_ctx *jit, ir_ref ref) -{ - if (GCC_GLOBAL_REGS) { - jit_STORE_IP(jit, ref); - } else { - ir_STORE(jit_EX(opline), ref); - } -} - static void jit_LOAD_IP_ADDR(zend_jit_ctx *jit, const zend_op *target) { - jit_LOAD_IP(jit, ir_CONST_ADDR(target)); + jit_STORE_IP(jit, ir_CONST_ADDR(target)); } static void zend_jit_track_last_valid_opline(zend_jit_ctx *jit) @@ -1008,7 +999,6 @@ static int zend_jit_save_call_chain(zend_jit_ctx *jit, uint32_t call_level) static int zend_jit_set_ip(zend_jit_ctx *jit, const zend_op *target) { ir_ref ref; - ir_ref addr = IR_UNUSED; if (jit->delayed_call_level) { if (!zend_jit_save_call_chain(jit, jit->delayed_call_level)) { @@ -1019,58 +1009,30 @@ static int zend_jit_set_ip(zend_jit_ctx *jit, const zend_op *target) if (jit->last_valid_opline) { zend_jit_use_last_valid_opline(jit); if (jit->last_valid_opline != target) { - if (GCC_GLOBAL_REGS) { - ref = jit_IP(jit); - } else { - addr = jit_EX(opline); - ref = ir_LOAD_A(addr); - } + ref = jit_IP(jit); if (target > jit->last_valid_opline) { ref = ir_ADD_OFFSET(ref, (uintptr_t)target - (uintptr_t)jit->last_valid_opline); } else { ref = ir_SUB_A(ref, ir_CONST_ADDR((uintptr_t)jit->last_valid_opline - (uintptr_t)target)); } - if (GCC_GLOBAL_REGS) { - jit_STORE_IP(jit, ref); - } else { - ir_STORE(addr, ref); - } + jit_STORE_IP(jit, ref); } } else { - if (GCC_GLOBAL_REGS) { - jit_STORE_IP(jit, ir_CONST_ADDR(target)); - } else { - ir_STORE(jit_EX(opline), ir_CONST_ADDR(target)); - } + jit_STORE_IP(jit, ir_CONST_ADDR(target)); } jit->reuse_ip = 0; zend_jit_set_last_valid_opline(jit, target); return 1; } -static int zend_jit_set_ip_ex(zend_jit_ctx *jit, const zend_op *target, bool set_ip_reg) -{ - if (!GCC_GLOBAL_REGS && set_ip_reg && !jit->last_valid_opline) { - /* Optimization to avoid duplicate constant load */ - ir_STORE(jit_EX(opline), ir_HARD_COPY_A(ir_CONST_ADDR(target))); - return 1; - } - return zend_jit_set_ip(jit, target); -} - static void jit_SET_EX_OPLINE(zend_jit_ctx *jit, const zend_op *target) { if (jit->last_valid_opline == target) { zend_jit_use_last_valid_opline(jit); - if (GCC_GLOBAL_REGS) { - // EX(opline) = opline - ir_STORE(jit_EX(opline), jit_IP(jit)); - } + // EX(opline) = opline + ir_STORE(jit_EX(opline), jit_IP(jit)); } else { ir_STORE(jit_EX(opline), ir_CONST_ADDR(target)); - if (!GCC_GLOBAL_REGS) { - zend_jit_reset_last_valid_opline(jit); - } } } @@ -1912,6 +1874,18 @@ static void zend_jit_check_timeout(zend_jit_ctx *jit, const zend_op *opline, con } } +static void zend_jit_vm_enter(zend_jit_ctx *jit, ir_ref to_opline) +{ + // ZEND_VM_ENTER() + ir_RETURN(ir_OR_A(to_opline, ir_CONST_ADDR(ZEND_VM_ENTER_BIT))); +} + +static void zend_jit_vm_leave(zend_jit_ctx *jit, ir_ref to_opline) +{ + // ZEND_VM_LEAVE() + ir_RETURN(ir_OR_A(to_opline, ir_CONST_ADDR(ZEND_VM_ENTER_BIT))); +} + /* stubs */ static int zend_jit_exception_handler_stub(zend_jit_ctx *jit) @@ -1929,14 +1903,8 @@ static int zend_jit_exception_handler_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_CONST_FUNC(handler)); } else { - ir_ref ref, if_negative; - - ref = ir_CALL_1(IR_I32, ir_CONST_FC_FUNC(handler), jit_FP(jit)); - if_negative = ir_IF(ir_LT(ref, ir_CONST_U32(0))); - ir_IF_TRUE(if_negative); - ir_MERGE_WITH_EMPTY_FALSE(if_negative); - ref = ir_PHI_2(IR_I32, ref, ir_CONST_I32(1)); - ir_RETURN(ref); + ir_ref ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + zend_jit_vm_enter(jit, ref); } } return 1; @@ -2014,10 +1982,8 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) { ir_ref if_timeout, if_exception; - if (GCC_GLOBAL_REGS) { - // EX(opline) = opline - ir_STORE(jit_EX(opline), jit_IP(jit)); - } + // EX(opline) = opline + ir_STORE(jit_EX(opline), jit_IP(jit)); ir_STORE(jit_EG(vm_interrupt), ir_CONST_U8(0)); if_timeout = ir_IF(ir_EQ(ir_LOAD_U8(jit_EG(timed_out)), ir_CONST_U8(0))); @@ -2039,7 +2005,7 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(1)); + zend_jit_vm_enter(jit, jit_IP(jit)); } return 1; } @@ -2059,7 +2025,7 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) } else if (GCC_GLOBAL_REGS) { ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_leave_nested_func_helper), call_info); } else { - ir_TAILCALL_2(IR_I32, ir_CONST_FC_FUNC(zend_jit_leave_nested_func_helper), call_info, jit_FP(jit)); + ir_TAILCALL_3(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_leave_nested_func_helper), jit_FP(jit), jit_IP(jit), call_info); } ir_IF_TRUE(if_top); @@ -2070,7 +2036,7 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) } else if (GCC_GLOBAL_REGS) { ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_leave_top_func_helper), call_info); } else { - ir_TAILCALL_2(IR_I32, ir_CONST_FC_FUNC(zend_jit_leave_top_func_helper), call_info, jit_FP(jit)); + ir_TAILCALL_3(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_leave_top_func_helper), jit_FP(jit), jit_IP(jit), call_info); } return 1; @@ -2209,9 +2175,7 @@ static int zend_jit_icall_throw_stub(zend_jit_ctx *jit) // JIT: opline = EG(exception_op); jit_STORE_IP(jit, jit_EG(exception_op)); - if (GCC_GLOBAL_REGS) { - ir_STORE(jit_EX(opline), jit_IP(jit)); - } + ir_STORE(jit_EX(opline), jit_IP(jit)); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler)); @@ -2234,7 +2198,7 @@ static int zend_jit_leave_throw_stub(zend_jit_ctx *jit) ir_MERGE_WITH_EMPTY_TRUE(if_set); // JIT: opline = EG(exception_op); - jit_LOAD_IP(jit, jit_EG(exception_op)); + jit_STORE_IP(jit, jit_EG(exception_op)); if (GCC_GLOBAL_REGS) { ir_STORE(jit_EX(opline), jit_IP(jit)); @@ -2242,7 +2206,7 @@ static int zend_jit_leave_throw_stub(zend_jit_ctx *jit) // JIT: HANDLE_EXCEPTION() ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler)); } else { - ir_RETURN(ir_CONST_I32(2)); // ZEND_VM_LEAVE + zend_jit_vm_leave(jit, jit_IP(jit)); } return 1; @@ -2339,13 +2303,7 @@ static int zend_jit_hybrid_loop_hot_counter_stub(zend_jit_ctx *jit) static ir_ref _zend_jit_orig_opline_handler(zend_jit_ctx *jit, ir_ref offset) { - ir_ref addr; - - if (GCC_GLOBAL_REGS) { - addr = ir_ADD_A(offset, jit_IP(jit)); - } else { - addr = ir_ADD_A(offset, ir_LOAD_A(jit_EX(opline))); - } + ir_ref addr = ir_ADD_A(offset, jit_IP(jit)); return ir_LOAD_A(addr); } @@ -2433,7 +2391,7 @@ static int zend_jit_trace_halt_stub(zend_jit_ctx *jit) jit_STORE_IP(jit, IR_NULL); ir_RETURN(IR_VOID); } else { - ir_RETURN(ir_CONST_I32(-1)); // ZEND_VM_RETURN + ir_RETURN(ir_CONST_ADDR(ZEND_VM_ENTER_BIT)); // ZEND_VM_RETURN } return 1; } @@ -2443,7 +2401,7 @@ static int zend_jit_trace_escape_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(1)); // ZEND_VM_ENTER + zend_jit_vm_enter(jit, jit_IP(jit)); } return 1; @@ -2453,10 +2411,8 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) { ir_ref ref, ret, if_zero, addr; - if (GCC_GLOBAL_REGS) { - // EX(opline) = opline - ir_STORE(jit_EX(opline), jit_IP(jit)); - } + // EX(opline) = opline + ir_STORE(jit_EX(opline), jit_IP(jit)); ret = ir_EXITCALL(ir_CONST_FC_FUNC(zend_jit_trace_exit)); @@ -2464,14 +2420,15 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) ir_IF_TRUE(if_zero); + ref = jit_EG(current_execute_data); + jit_STORE_FP(jit, ir_LOAD_A(ref)); + ref = ir_LOAD_A(jit_EX(opline)); + jit_STORE_IP(jit, ref); + if (GCC_GLOBAL_REGS) { - ref = jit_EG(current_execute_data); - jit_STORE_FP(jit, ir_LOAD_A(ref)); - ref = ir_LOAD_A(jit_EX(opline)); - jit_STORE_IP(jit, ref); ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(1)); // ZEND_VM_ENTER + zend_jit_vm_enter(jit, ref); } ir_IF_FALSE(if_zero); @@ -2481,10 +2438,8 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) ref = jit_EG(current_execute_data); jit_STORE_FP(jit, ir_LOAD_A(ref)); - if (GCC_GLOBAL_REGS) { - ref = ir_LOAD_A(jit_EX(opline)); - jit_STORE_IP(jit, ref); - } + ref = ir_LOAD_A(jit_EX(opline)); + jit_STORE_IP(jit, ref); // check for interrupt (try to avoid this ???) zend_jit_check_timeout(jit, NULL, NULL); @@ -2496,9 +2451,8 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) #if defined(IR_TARGET_X86) addr = ir_CAST_FC_FUNC(addr); #endif - ref = ir_CALL_1(IR_I32, addr, jit_FP(jit)); - ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); - ir_RETURN(ir_CONST_I32(1)); // ZEND_VM_ENTER + ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit)); + zend_jit_vm_enter(jit, ref); } return 1; @@ -2509,7 +2463,7 @@ static int zend_jit_undefined_offset_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key)); } else { - ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key), jit_FP(jit)); + ir_TAILCALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key), jit_FP(jit), jit_IP(jit)); } return 1; @@ -2520,7 +2474,7 @@ static int zend_jit_undefined_key_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key)); } else { - ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key), jit_FP(jit)); + ir_TAILCALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key), jit_FP(jit), jit_IP(jit)); } return 1; @@ -2702,6 +2656,10 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) #else /* IR_TARGET_x86 */ jit->ctx.fixed_stack_frame_size = sizeof(void*) * 11; /* 4 saved registers and 7 spill slots (4 bytes) */ #endif + /* JIT-ed code is called only from execute_ex, which takes care + * of saving ZREG_FP, ZREG_IP when GCC_GLOBAL_REGS is 1, so we don't + * have to save them. + */ if (GCC_GLOBAL_REGS) { jit->ctx.fixed_save_regset = IR_REGSET_PRESERVED & ~((1<ctx.flags |= IR_FASTCALL_FUNC; } @@ -3960,18 +3920,10 @@ static int jit_CMP_IP(zend_jit_ctx *jit, ir_op op, const zend_op *next_opline) ir_ref ref; #if 1 - if (GCC_GLOBAL_REGS) { - ref = jit_IP32(jit); - } else { - ref = ir_LOAD_U32(jit_EX(opline)); - } + ref = jit_IP32(jit); ref = ir_CMP_OP(op, ref, ir_CONST_U32((uint32_t)(uintptr_t)next_opline)); #else - if (GCC_GLOBAL_REGS) { - ref = jit_IP(jit); - } else { - ref = ir_LOAD_A(jit_EX(opline)); - } + ref = jit_IP(jit); ref = ir_CMP_OP(op, ref, ir_CONST_ADDR(next_opline)); #endif return ref; @@ -4144,10 +4096,13 @@ static void zend_jit_recv_entry(zend_jit_ctx *jit, int b) /* Insert a MERGE block with additional ENTRY input between predecessor and this one */ ir_ENTRY(ref, bb->start); if (!GCC_GLOBAL_REGS) { - /* 2 is hardcoded reference to IR_PARAM */ + /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); jit_STORE_FP(jit, 2); + ZEND_ASSERT(jit->ctx.ir_base[3].op == IR_PARAM); + ZEND_ASSERT(jit->ctx.ir_base[3].op3 == 2); + jit_STORE_IP(jit, 3); } ir_MERGE_WITH(ref); @@ -4162,10 +4117,13 @@ static void zend_jit_osr_entry(zend_jit_ctx *jit, int b) /* Insert a MERGE block with additional ENTRY input between predecessor and this one */ ir_ENTRY(ref, bb->start); if (!GCC_GLOBAL_REGS) { - /* 2 is hardcoded reference to IR_PARAM */ + /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); jit_STORE_FP(jit, 2); + ZEND_ASSERT(jit->ctx.ir_base[3].op == IR_PARAM); + ZEND_ASSERT(jit->ctx.ir_base[3].op3 == 2); + jit_STORE_IP(jit, 3); } ir_MERGE_WITH(ref); @@ -4175,17 +4133,19 @@ static ir_ref zend_jit_continue_entry(zend_jit_ctx *jit, ir_ref src, unsigned in { ir_ENTRY(src, label); if (!GCC_GLOBAL_REGS) { - /* 2 is hardcoded reference to IR_PARAM */ + /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); jit_STORE_FP(jit, 2); + ZEND_ASSERT(jit->ctx.ir_base[3].op == IR_PARAM); + ZEND_ASSERT(jit->ctx.ir_base[3].op3 == 2); + jit_STORE_IP(jit, 3); } return ir_END(); } static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_throw) { - ir_ref ref; const void *handler; zend_jit_set_ip(jit, opline); @@ -4197,8 +4157,8 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th if (GCC_GLOBAL_REGS) { ir_CALL(IR_VOID, ir_CONST_FUNC(handler)); } else { - ref = jit_FP(jit); - ref = ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(handler), ref); + ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + jit_STORE_IP(jit, ip); } if (may_throw) { zend_jit_check_exception(jit); @@ -4256,12 +4216,10 @@ static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline) || opline->opcode == ZEND_MATCH_ERROR || opline->opcode == ZEND_THROW || opline->opcode == ZEND_VERIFY_NEVER_TYPE)) { - ref = jit_FP(jit); - ir_CALL_1(IR_I32, ir_CONST_FC_FUNC(handler), ref); - ir_RETURN(ir_CONST_I32(1)); + ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + zend_jit_vm_enter(jit, ip); } else { - ref = jit_FP(jit); - ir_TAILCALL_1(IR_I32, ir_CONST_FC_FUNC(handler), ref); + ir_TAILCALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); } } if (jit->b >= 0) { @@ -10319,7 +10277,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (num_args) { ip = ir_ADD_OFFSET(ip, num_args * sizeof(zend_op)); } - jit_LOAD_IP(jit, ip); + jit_STORE_IP(jit, ip); } if (!trace && op_array == &func->op_array && call_num_args >= op_array->required_num_args) { @@ -10341,7 +10299,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } ip = ir_LOAD_A(ir_ADD_OFFSET(func_ref, offsetof(zend_op_array, opcodes))); } - jit_LOAD_IP(jit, ip); + jit_STORE_IP(jit, ip); helper = ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper); } else { helper = ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper_no_skip_recv); @@ -10349,7 +10307,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (GCC_GLOBAL_REGS) { ir_CALL(IR_VOID, helper); } else { - ir_CALL_1(IR_VOID, helper, jit_FP(jit)); + ir_ref ref = ir_CALL_2(IR_ADDR, helper, jit_FP(jit), jit_IP(jit)); + jit_STORE_IP(jit, ref); } } } else { @@ -10365,7 +10324,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } ip = ir_LOAD_A(ir_ADD_OFFSET(func_ref, offsetof(zend_op_array, opcodes))); } - jit_LOAD_IP(jit, ip); + jit_STORE_IP(jit, ip); // JIT: num_args = EX_NUM_ARGS(); ir_ref num_args, first_extra_arg; @@ -10385,7 +10344,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (GCC_GLOBAL_REGS) { ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper)); } else { - ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper), jit_FP(jit)); + ir_ref ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper), jit_FP(jit), jit_IP(jit)); + jit_STORE_IP(jit, ref); } ir_END_list(merge_inputs); ir_IF_FALSE(if_extra_args); @@ -10407,13 +10367,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ref = ir_ZEXT_A(ref); } - if (GCC_GLOBAL_REGS) { - jit_STORE_IP(jit, ir_ADD_A(jit_IP(jit), ref)); - } else { - ir_ref addr = jit_EX(opline); - - ir_STORE(addr, ir_ADD_A(ir_LOAD_A(addr), ref)); - } + jit_STORE_IP(jit, ir_ADD_A(jit_IP(jit), ref)); } ir_END_list(merge_inputs); @@ -10462,7 +10416,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop < ZEND_JIT_TRACE_STOP_INTERPRETER)) { ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END); jit_SET_EX_OPLINE(jit, trace[1].opline); - } else if (GCC_GLOBAL_REGS) { + } else { // EX(opline) = opline ir_STORE(jit_EX(opline), jit_IP(jit)); } @@ -10529,7 +10483,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(1)); + zend_jit_vm_enter(jit, jit_IP(jit)); } } while (0); @@ -11129,7 +11083,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, ir_IF_TRUE_cold(if_slow); if (!GCC_GLOBAL_REGS) { - ref = ir_CALL_1(IR_I32, ir_CONST_FC_FUNC(zend_jit_leave_func_helper), jit_FP(jit)); + ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_leave_func_helper), jit_FP(jit), jit_IP(jit)); } else { ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_leave_func_helper)); } @@ -11145,7 +11099,8 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, } else if (GCC_GLOBAL_REGS) { ir_GUARD(jit_IP(jit), jit_STUB_ADDR(jit, jit_stub_trace_halt)); } else { - ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); + ir_GUARD(ir_NE(ref, ir_CONST_ADDR(ZEND_VM_ENTER_BIT)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); + jit_STORE_IP(jit, ref); } } @@ -11213,26 +11168,20 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, && (JIT_G(current_frame) && !TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) { zend_jit_reset_last_valid_opline(jit); } else { - if (GCC_GLOBAL_REGS) { - /* We add extra RLOAD and RSTORE to make fusion for persistent register - * mov (%FP), %IP - * add $0x1c, %IP - * The naive (commented) code leads to extra register allocation and move. - * mov (%FP), %tmp - * add $0x1c, %tmp - * mov %tmp, %FP - */ + /* We add extra RLOAD and RSTORE to make fusion for persistent register + * mov (%FP), %IP + * add $0x1c, %IP + * The naive (commented) code leads to extra register allocation and move. + * mov (%FP), %tmp + * add $0x1c, %tmp + * mov %tmp, %FP + */ #if 0 - jit_STORE_IP(jit, ir_ADD_OFFSET(ir_LOAD_A(jit_EX(opline)), sizeof(zend_op))); + jit_STORE_IP(jit, ir_ADD_OFFSET(ir_LOAD_A(jit_EX(opline)), sizeof(zend_op))); #else - jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); - jit_STORE_IP(jit, ir_ADD_OFFSET(jit_IP(jit), sizeof(zend_op))); + jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); + jit_STORE_IP(jit, ir_ADD_OFFSET(jit_IP(jit), sizeof(zend_op))); #endif - } else { - ir_ref ref = jit_EX(opline); - - ir_STORE(ref, ir_ADD_OFFSET(ir_LOAD_A(ref), sizeof(zend_op))); - } } if (cold_path) { @@ -11295,20 +11244,14 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, // JIT: if (EG(exception)) ir_GUARD_NOT(ir_LOAD_A(jit_EG(exception)), jit_STUB_ADDR(jit, jit_stub_leave_throw)); // JIT: opline = EX(opline) + 1 - if (GCC_GLOBAL_REGS) { - jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); - jit_STORE_IP(jit, ir_ADD_OFFSET(jit_IP(jit), sizeof(zend_op))); - } else { - ir_ref ref = jit_EX(opline); - - ir_STORE(ref, ir_ADD_OFFSET(ir_LOAD_A(ref), sizeof(zend_op))); - } + jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); + jit_STORE_IP(jit, ir_ADD_OFFSET(jit_IP(jit), sizeof(zend_op))); } if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - ir_RETURN(ir_CONST_I32(2)); // ZEND_VM_LEAVE + zend_jit_vm_leave(jit, jit_IP(jit)); } jit->b = -1; @@ -16745,8 +16688,10 @@ static int zend_jit_start(zend_jit_ctx *jit, const zend_op_array *op_array, zend jit->bb_edges = zend_arena_calloc(&CG(arena), count, sizeof(ir_ref)); if (!GCC_GLOBAL_REGS) { - ir_ref ref = ir_PARAM(IR_ADDR, "execute_data", 1); - jit_STORE_FP(jit, ref); + ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); + ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); + jit_STORE_FP(jit, execute_data_ref); + jit_STORE_IP(jit, opline_ref); jit->ctx.flags |= IR_FASTCALL_FUNC; } @@ -17129,8 +17074,18 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr if (GCC_GLOBAL_REGS) { ir_CALL(IR_VOID, ir_CONST_FUNC(handler)); } else { - ref = jit_FP(jit); - ref = ir_CALL_1(IR_I32, ir_CONST_FC_FUNC(handler), ref); + ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + if (opline->opcode == ZEND_RETURN || + opline->opcode == ZEND_RETURN_BY_REF || + opline->opcode == ZEND_DO_UCALL || + opline->opcode == ZEND_DO_FCALL_BY_NAME || + opline->opcode == ZEND_DO_FCALL || + opline->opcode == ZEND_GENERATOR_CREATE) { + + jit_STORE_IP(jit, ir_AND_A(ref, ir_CONST_ADDR(~ZEND_VM_ENTER_BIT))); + } else { + jit_STORE_IP(jit, ref); + } } if (may_throw && opline->opcode != ZEND_RETURN @@ -17170,10 +17125,9 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr ir_GUARD(ir_NE(jit_IP(jit), ir_CONST_ADDR(zend_jit_halt_op)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); } - } else if (GCC_GLOBAL_REGS) { - ir_GUARD(jit_IP(jit), jit_STUB_ADDR(jit, jit_stub_trace_halt)); } else { - ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); + /* IP has been cleared of ZEND_VM_ENTER_BIT already */ + ir_GUARD(jit_IP(jit), jit_STUB_ADDR(jit, jit_stub_trace_halt)); } } else if (opline->opcode == ZEND_GENERATOR_RETURN || opline->opcode == ZEND_YIELD || @@ -17309,8 +17263,10 @@ static int zend_jit_trace_start(zend_jit_ctx *jit, if (!GCC_GLOBAL_REGS) { if (!parent) { - ir_ref ref = ir_PARAM(IR_ADDR, "execute_data", 1); - jit_STORE_FP(jit, ref); + ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); + ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); + jit_STORE_FP(jit, execute_data_ref); + jit_STORE_IP(jit, opline_ref); jit->ctx.flags |= IR_FASTCALL_FUNC; } } @@ -17423,7 +17379,7 @@ static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const #if defined(IR_TARGET_X86) addr = ir_CAST_FC_FUNC(addr); #endif - ref = ir_CALL_1(IR_I32, addr, jit_FP(jit)); + ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit)); if (opline && (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF @@ -17431,11 +17387,11 @@ static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const || opline->opcode == ZEND_GENERATOR_CREATE || opline->opcode == ZEND_YIELD || opline->opcode == ZEND_YIELD_FROM)) { - ir_RETURN(ref); + zend_jit_vm_enter(jit, ref); return 1; } } - ir_RETURN(ir_CONST_I32(2)); // ZEND_VM_LEAVE + zend_jit_vm_enter(jit, jit_IP(jit)); } return 1; } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index d1bc2bdbd77cf..68c096d9d3df2 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -16,6 +16,11 @@ +----------------------------------------------------------------------+ */ +#include "zend_jit.h" +#include "zend_jit_internal.h" +#include "zend_shared_alloc.h" +#include "ir/ir.h" + static zend_jit_trace_info *zend_jit_traces = NULL; static const void **zend_jit_exit_groups = NULL; @@ -7433,7 +7438,7 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n original_handler = 1; } } - zend_jit_set_ip_ex(&ctx, opline, original_handler); + zend_jit_set_ip(&ctx, opline); } zend_jit_trace_return(&ctx, original_handler, opline); diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index c98376d5a1f69..0ce7f082ae15f 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -46,7 +46,7 @@ register const zend_op* volatile opline __asm__("x28"); # pragma GCC diagnostic warning "-Wvolatile-register-var" #endif -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(uint32_t call_info EXECUTE_DATA_DC) +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info) { zend_execute_data *old_execute_data; @@ -75,19 +75,19 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(uint32_t zval_ptr_dtor(EX_VAR(old_opline->result.var)); } #ifndef HAVE_GCC_GLOBAL_REGS - return 2; // ZEND_VM_LEAVE + return (zend_op*)((uintptr_t)EG(current_execute_data)->opline | ZEND_VM_ENTER_BIT); #endif } else { EX(opline)++; #ifdef HAVE_GCC_GLOBAL_REGS opline = EX(opline); #else - return 2; // ZEND_VM_LEAVE + return (zend_op*)((uintptr_t)EX(opline) | ZEND_VM_ENTER_BIT); #endif } } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(uint32_t call_info EXECUTE_DATA_DC) +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info) { if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { @@ -105,11 +105,11 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(uint32_t ca #ifdef HAVE_GCC_GLOBAL_REGS opline = zend_jit_halt_op; #else - return -1; // ZEND_VM_RETURN + return (const zend_op*)ZEND_VM_ENTER_BIT; // ZEND_VM_RETURN #endif } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(EXECUTE_DATA_D) +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(ZEND_OPCODE_HANDLER_ARGS) { uint32_t call_info = EX_CALL_INFO(); @@ -120,7 +120,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(EXECUTE_DATA_D) } } -static void ZEND_FASTCALL zend_jit_copy_extra_args_helper_ex(bool skip_recv EXECUTE_DATA_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper_ex(ZEND_OPCODE_HANDLER_ARGS_EX bool skip_recv) { zend_op_array *op_array = &EX(func)->op_array; @@ -132,11 +132,7 @@ static void ZEND_FASTCALL zend_jit_copy_extra_args_helper_ex(bool skip_recv EXEC if (skip_recv && EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ -#ifdef HAVE_GCC_GLOBAL_REGS opline += first_extra_arg; -#else - EX(opline) += first_extra_arg; -#endif } /* move extra args into separate array after all CV and TMP vars */ @@ -164,16 +160,20 @@ static void ZEND_FASTCALL zend_jit_copy_extra_args_helper_ex(bool skip_recv EXEC } while (src != end); } } + +#ifndef HAVE_GCC_GLOBAL_REGS + return opline; +#endif } -void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D) +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper(ZEND_OPCODE_HANDLER_ARGS) { - zend_jit_copy_extra_args_helper_ex(true EXECUTE_DATA_CC); + return zend_jit_copy_extra_args_helper_ex(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX true); } -void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D) +ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(ZEND_OPCODE_HANDLER_ARGS) { - zend_jit_copy_extra_args_helper_ex(false EXECUTE_DATA_CC); + return zend_jit_copy_extra_args_helper_ex(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX false); } bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D) @@ -312,9 +312,6 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H { zend_jit_op_array_hot_extension *jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); -#ifndef HAVE_GCC_GLOBAL_REGS - const zend_op *opline = EX(opline); -#endif *(jit_extension->counter) -= ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func)); @@ -332,9 +329,6 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H { zend_jit_op_array_hot_extension *jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); -#ifndef HAVE_GCC_GLOBAL_REGS - const zend_op *opline = EX(opline); -#endif *(jit_extension->counter) -= ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop)); @@ -403,14 +397,11 @@ zend_constant* ZEND_FASTCALL zend_jit_check_constant(const zval *key) return _zend_quick_get_constant(key, 0, 1); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_counter_helper(uint32_t cost ZEND_OPCODE_HANDLER_ARGS_DC) +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_counter_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t cost) { zend_jit_op_array_trace_extension *jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); size_t offset = jit_extension->offset; -#ifndef HAVE_GCC_GLOBAL_REGS - const zend_op *opline = EX(opline); -#endif *(ZEND_OP_TRACE_INFO(opline, offset)->counter) -= cost; @@ -421,15 +412,15 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_c opline = NULL; return; #else - return -1; + return (const zend_op*)ZEND_VM_ENTER_BIT; // ZEND_VM_RETURN() #endif } -#ifdef HAVE_GCC_GLOBAL_REGS execute_data = EG(current_execute_data); opline = execute_data ? EX(opline) : NULL; +#ifdef HAVE_GCC_GLOBAL_REGS return; #else - return 1; + return (const zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT); // ZEND_VM_ENTER() / ZEND_VM_RETURN() #endif } else { zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->orig_handler; @@ -678,15 +669,14 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, int last_loop_level = -1; const zend_op *last_loop_opline = NULL; const zend_op_array *unrolled_calls[ZEND_JIT_TRACE_MAX_CALL_DEPTH + ZEND_JIT_TRACE_MAX_RET_DEPTH]; -#ifdef HAVE_GCC_GLOBAL_REGS zend_execute_data *prev_execute_data = ex; +#ifdef HAVE_GCC_GLOBAL_REGS execute_data = ex; opline = EX(opline) = op; #else - int rc; zend_execute_data *execute_data = ex; - const zend_op *opline = EX(opline); + const zend_op *opline = EX(opline) = op; #endif zend_execute_data *prev_call = EX(call); @@ -992,40 +982,29 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, #ifdef HAVE_GCC_GLOBAL_REGS handler(); if (UNEXPECTED(opline == zend_jit_halt_op)) { +#else + opline = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED(((uintptr_t)opline & ~ZEND_VM_ENTER_BIT) == 0)) { +#endif stop = ZEND_JIT_TRACE_STOP_RETURN; opline = NULL; halt = ZEND_JIT_TRACE_HALT; break; } - if (UNEXPECTED(execute_data != prev_execute_data)) { -#else - rc = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - if (rc != 0) { - if (rc < 0) { - stop = ZEND_JIT_TRACE_STOP_RETURN; - opline = NULL; - halt = ZEND_JIT_TRACE_HALT; - break; - } else if (execute_data == EG(current_execute_data)) { - /* return after interrupt handler */ - rc = 0; - } +#ifndef HAVE_GCC_GLOBAL_REGS + if ((uintptr_t)opline & ZEND_VM_ENTER_BIT) { + opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT); execute_data = EG(current_execute_data); - opline = EX(opline); + } #endif + if (UNEXPECTED(execute_data != prev_execute_data)) { op_array = &EX(func)->op_array; jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); if (UNEXPECTED(!jit_extension) || UNEXPECTED(!(jit_extension->func_info.flags & ZEND_FUNC_JIT_ON_HOT_TRACE))) { -#ifdef HAVE_GCC_GLOBAL_REGS if (execute_data->prev_execute_data != prev_execute_data) { -#else - if (rc < 0) { -#endif - stop = ZEND_JIT_TRACE_STOP_RETURN; - } else { stop = ZEND_JIT_TRACE_STOP_INTERPRETER; } break; @@ -1036,13 +1015,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, op_array = jit_extension->op_array; } -#ifdef HAVE_GCC_GLOBAL_REGS if (execute_data->prev_execute_data == prev_execute_data) { -#else - if (rc == 0) { - /* pass */ - } else if (rc == 1) { -#endif /* Enter into function */ prev_call = NULL; if (level > ZEND_JIT_TRACE_MAX_CALL_DEPTH) { @@ -1164,9 +1137,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, TRACE_RECORD(ZEND_JIT_TRACE_BACK, 0, op_array); } } -#ifdef HAVE_GCC_GLOBAL_REGS prev_execute_data = execute_data; -#endif } if (EX(call) != prev_call) { if (EX(call) @@ -1191,10 +1162,6 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, } } -#ifndef HAVE_GCC_GLOBAL_REGS - opline = EX(opline); -#endif - if (!func || (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) || (func->common.fn_flags & ZEND_ACC_NEVER_CACHE) @@ -1219,10 +1186,6 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, prev_call = EX(call); } -#ifndef HAVE_GCC_GLOBAL_REGS - opline = EX(opline); -#endif - if (UNEXPECTED(opline->opcode == ZEND_HANDLE_EXCEPTION)) { /* Abort trace because of exception */ stop = ZEND_JIT_TRACE_STOP_EXCEPTION; @@ -1346,11 +1309,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, TRACE_END(ZEND_JIT_TRACE_END, stop, end_opline); -#ifdef HAVE_GCC_GLOBAL_REGS if (!halt) { EX(opline) = opline; } -#endif #ifdef HAVE_GCC_GLOBAL_REGS execute_data = save_execute_data; diff --git a/sapi/phpdbg/tests/watch_006.phpt b/sapi/phpdbg/tests/watch_006.phpt index 5b5ca9ee57c0e..c5f53a37510c5 100644 --- a/sapi/phpdbg/tests/watch_006.phpt +++ b/sapi/phpdbg/tests/watch_006.phpt @@ -2,9 +2,7 @@ Test multiple watch elements pointing to the same watchpoint --SKIPIF-- Date: Tue, 15 Apr 2025 09:41:04 +0200 Subject: [PATCH 342/503] Fix GH-18108 gen_stub: Using $this when not in object context --- build/gen_stub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index e69846733a9d9..d3ffc04c3f890 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2174,7 +2174,7 @@ public function enterNode(Node $expr) static function (Expr $expr) use ($allConstInfos, &$isUnknownConstValue) { // $expr is a ConstFetch with a name of a C macro here if (!$expr instanceof Expr\ConstFetch) { - throw new Exception($this->getVariableTypeName() . " " . $this->name->__toString() . " has an unsupported value"); + throw new Exception("Expression at line " . $expr->getStartLine() . " must be a global, non-magic constant"); } $constName = $expr->name->__toString(); From ea387fcfb76d5b77ad1cddf76b2a5894025ded2e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:08:12 +0200 Subject: [PATCH 343/503] Avoid useless initializations of fci/fcc in array functions (#18273) These cause cache misses due to global access, in phpstan (notably the array_map). Initializing these isn't necessary because ZPP initializes it for us. Only for optional arguments do we need to be careful; for `array_filter` we still reset the `fci` but not `fci_cache` because `fci` is not necessarily set by ZPP but is conditionally used to access `fci_cache`. --- ext/standard/array.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 4ab3a690120b2..cabb43d8a914c 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6439,7 +6439,7 @@ PHP_FUNCTION(array_reduce) zval args[2]; zval *operand; zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; zval *initial = NULL; HashTable *htbl; @@ -6515,7 +6515,7 @@ PHP_FUNCTION(array_filter) zend_long use_type = 0; zend_string *string_key; zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; zend_ulong num_key; ZEND_PARSE_PARAMETERS_START(1, 3) @@ -6649,7 +6649,7 @@ PHP_FUNCTION(array_find) { HashTable *array; zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ARRAY_HT(array) @@ -6665,7 +6665,7 @@ PHP_FUNCTION(array_find_key) { HashTable *array; zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ARRAY_HT(array) @@ -6681,7 +6681,7 @@ PHP_FUNCTION(array_any) { HashTable *array; zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ARRAY_HT(array) @@ -6697,7 +6697,7 @@ PHP_FUNCTION(array_all) { HashTable *array; zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info_cache fci_cache; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ARRAY_HT(array) @@ -6714,8 +6714,8 @@ PHP_FUNCTION(array_map) zval *arrays = NULL; int n_arrays = 0; zval result; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; int i; uint32_t k, maxlen = 0; From 0a6326c6ac93c53b8804d23d1d42bf91475a260d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:58:33 +0200 Subject: [PATCH 344/503] Fix uouv when handling empty options in ZipArchive::addGlob() Reported by OpenAI AARDVARK. php_zip_parse_option is only called when options are passed to the function. Prior to this patch, php_zip_parse_option was responsible for zeroing the opts variable. So in the case when php_zip_parse_option is not called, opts remains uninitialized yet it is being used anyway. By just always zeroing opts at declaration time, we avoid this issue and we are unlikely to reintroduce this in the future. Closes GH-18329. --- NEWS | 3 +++ ext/zip/php_zip.c | 4 ++-- ext/zip/tests/addGlob_empty_options.phpt | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 ext/zip/tests/addGlob_empty_options.phpt diff --git a/NEWS b/NEWS index 7d660e26cef75..a3f2990962d42 100644 --- a/NEWS +++ b/NEWS @@ -43,6 +43,9 @@ PHP NEWS leads to negative stream position). (David Carlier) . Fix resource leak in iptcembed() on error. (nielsdos) +- Zip: + . Fix uouv when handling empty options in ZipArchive::addGlob(). (nielsdos) + 10 Apr 2025, PHP 8.3.20 - Core: diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 172057685105b..be096ad56e29d 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -354,13 +354,13 @@ typedef struct { #endif } zip_options; +/* Expects opts to be zero-initialized. */ static int php_zip_parse_options(HashTable *options, zip_options *opts) /* {{{ */ { zval *option; /* default values */ - memset(opts, 0, sizeof(zip_options)); opts->flags = ZIP_FL_OVERWRITE; opts->comp_method = -1; /* -1 to not change default */ #ifdef HAVE_ENCRYPTION @@ -1732,7 +1732,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* size_t path_len = 1; zend_long glob_flags = 0; HashTable *options = NULL; - zip_options opts; + zip_options opts = {0}; int found; zend_string *pattern; diff --git a/ext/zip/tests/addGlob_empty_options.phpt b/ext/zip/tests/addGlob_empty_options.phpt new file mode 100644 index 0000000000000..f4a4126059a7b --- /dev/null +++ b/ext/zip/tests/addGlob_empty_options.phpt @@ -0,0 +1,22 @@ +--TEST-- +addGlob with empty options +--EXTENSIONS-- +zip +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$zip->addGlob(__FILE__, 0, []); +var_dump($zip->statIndex(0)['name'] === __FILE__); +$zip->close(); + +?> +--CLEAN-- + +--EXPECT-- +bool(true) From 91c6c727d516716855d6fa8bd75908cd3249d17e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:59:25 +0200 Subject: [PATCH 345/503] Fix memory leak when handling a too long path in ZipArchive::addGlob() Closes GH-18330. --- NEWS | 2 ++ ext/zip/php_zip.c | 3 +++ .../addGlob_too_long_add_path_option.phpt | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 ext/zip/tests/addGlob_too_long_add_path_option.phpt diff --git a/NEWS b/NEWS index a3f2990962d42..22ce2f45ecca0 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,8 @@ PHP NEWS - Zip: . Fix uouv when handling empty options in ZipArchive::addGlob(). (nielsdos) + . Fix memory leak when handling a too long path in ZipArchive::addGlob(). + (nielsdos) 10 Apr 2025, PHP 8.3.20 diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index be096ad56e29d..45b83aeae63bc 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1796,6 +1796,9 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* if (opts.add_path) { if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) { + if (basename) { + zend_string_release_ex(basename, 0); + } php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)", MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len)); zend_array_destroy(Z_ARR_P(return_value)); diff --git a/ext/zip/tests/addGlob_too_long_add_path_option.phpt b/ext/zip/tests/addGlob_too_long_add_path_option.phpt new file mode 100644 index 0000000000000..9598eeca40a89 --- /dev/null +++ b/ext/zip/tests/addGlob_too_long_add_path_option.phpt @@ -0,0 +1,21 @@ +--TEST-- +addGlob with too long add_path option +--EXTENSIONS-- +zip +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$zip->addGlob(__FILE__, 0, ['add_path' => str_repeat('A', PHP_MAXPATHLEN - 2)]); +$zip->close(); + +?> +--CLEAN-- + +--EXPECTF-- +Warning: ZipArchive::addGlob(): Entry name too long (max: %d, %d given) in %s on line %d From c905d5910645b6024faee6ce791ab884e739c767 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 16 Apr 2025 00:09:35 +0200 Subject: [PATCH 346/503] Fix NULL deref on high modification key We should re-index in the loop. Closes GH-18331. --- NEWS | 1 + ext/ldap/ldap.c | 8 +++++--- ext/ldap/tests/ldap_modify_batch_error.phpt | 13 +++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 22ce2f45ecca0..ac31131ea9d22 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ PHP NEWS - LDAP: . Fixed bug GH-17776 (LDAP_OPT_X_TLS_* options can't be overridden). (Remi) + . Fix NULL deref on high modification key. (nielsdos) - libxml: . Fixed custom external entity loader returning an invalid resource leading diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 1a878bfc58483..6c005337346b5 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2785,12 +2785,12 @@ PHP_FUNCTION(ldap_modify_batch) ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0); /* for each modification */ - for (i = 0; i < num_mods; i++) { + i = 0; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mods), fetched) { /* allocate the modification struct */ ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0); /* fetch the relevant data */ - fetched = zend_hash_index_find(Z_ARRVAL_P(mods), i); mod = fetched; _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib); @@ -2855,7 +2855,9 @@ PHP_FUNCTION(ldap_modify_batch) /* NULL-terminate values */ ldap_mods[i]->mod_bvalues[num_modvals] = NULL; } - } + + i++; + } ZEND_HASH_FOREACH_END(); /* NULL-terminate modifications */ ldap_mods[num_mods] = NULL; diff --git a/ext/ldap/tests/ldap_modify_batch_error.phpt b/ext/ldap/tests/ldap_modify_batch_error.phpt index bce62cafb2791..0ac093b4a0341 100644 --- a/ext/ldap/tests/ldap_modify_batch_error.phpt +++ b/ext/ldap/tests/ldap_modify_batch_error.phpt @@ -59,6 +59,16 @@ $mods = array( ) ); +var_dump(ldap_modify_batch($link, "dc=my-domain,$base", $mods)); + +// high key with invalid attribute type +$mods = [ + 99999 => [ + "attrib" => "weirdAttribute", + "modtype" => LDAP_MODIFY_BATCH_ADD, + "values" => ["value1"], + ], +]; var_dump(ldap_modify_batch($link, "dc=my-domain,$base", $mods)); ?> --CLEAN-- @@ -81,3 +91,6 @@ bool(false) Warning: ldap_modify_batch(): Batch Modify: Undefined attribute type in %s on line %d bool(false) + +Warning: ldap_modify_batch(): Batch Modify: Undefined attribute type in %s on line %d +bool(false) From ce7304f909396d623c4428c30fb1ad25c42d084d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 16 Apr 2025 00:23:48 +0200 Subject: [PATCH 347/503] Fix memory leak on error return of collation callback in pdo_sqlite We should destroy it when it's not IS_LONG, not when it's IS_LONG. Closes GH-18332. --- NEWS | 3 +++ ext/pdo_sqlite/pdo_sqlite.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 08a1bb902a33b..cd9bb021b9706 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,9 @@ PHP NEWS . Fixed GH-18276 - persistent connection - "zend_mm_heap corrupted" with setAttribute() (SakiTakamachi). +- PDO Sqlite: + . Fix memory leak on error return of collation callback. (nielsdos) + - SPL: . Fixed bug GH-18322 (SplObjectStorage debug handler mismanages memory). (nielsdos) diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index bc47c15a1eb5e..ff56d04049424 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -352,6 +352,7 @@ static int php_sqlite_collation_callback(void *context, int string1_len, const v zend_type_error("%s(): Return value of the callback must be of type int, %s returned", ZSTR_VAL(func_name), zend_zval_value_name(&retval)); zend_string_release(func_name); + zval_ptr_dtor(&retval); return FAILURE; } if (Z_LVAL(retval) > 0) { @@ -359,7 +360,6 @@ static int php_sqlite_collation_callback(void *context, int string1_len, const v } else if (Z_LVAL(retval) < 0) { ret = -1; } - zval_ptr_dtor(&retval); } zval_ptr_dtor(&zargs[0]); From 87499e44f29137847b95aa5cd1a130d1c3c5b276 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 16 Apr 2025 20:00:40 +0200 Subject: [PATCH 348/503] Fix use of magic const within const expr cast (GH-18338) Fixes OSS-Fuzz #410939023 --- Zend/tests/oss_fuzz_410939023.phpt | 11 +++++++++++ Zend/zend_compile.c | 3 +++ 2 files changed, 14 insertions(+) create mode 100644 Zend/tests/oss_fuzz_410939023.phpt diff --git a/Zend/tests/oss_fuzz_410939023.phpt b/Zend/tests/oss_fuzz_410939023.phpt new file mode 100644 index 0000000000000..9c024bf5b5b06 --- /dev/null +++ b/Zend/tests/oss_fuzz_410939023.phpt @@ -0,0 +1,11 @@ +--TEST-- +OSS-Fuzz #410939023: Use of magic const within const expr cast +--FILE-- + +--EXPECT-- +string(0) "" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4f18999ffa785..5c15832f80a89 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -12127,6 +12127,9 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ zend_eval_const_expr(&ast->child[0]); zend_eval_const_expr(&ast->child[1]); return; + case ZEND_AST_CAST: + zend_eval_const_expr(&ast->child[0]); + return; default: return; } From 8376904aeb636bc2a44dad4b712f1458ad0a65e1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 18 Apr 2025 00:34:46 +0200 Subject: [PATCH 349/503] Implement GH-17321: Add setAuthorizer to Pdo\Sqlite (#17905) --- NEWS | 1 + UPGRADING | 5 + ext/pdo_sqlite/pdo_sqlite.c | 32 +++++- ext/pdo_sqlite/pdo_sqlite.stub.php | 12 +++ ext/pdo_sqlite/pdo_sqlite_arginfo.h | 26 ++++- ext/pdo_sqlite/php_pdo_sqlite_int.h | 1 + ext/pdo_sqlite/sqlite_driver.c | 85 ++++++++++++--- .../subclasses/pdosqlite_setauthorizer.phpt | 101 ++++++++++++++++++ .../pdosqlite_setauthorizer_trampoline.phpt | 43 ++++++++ ...lite_setauthorizer_trampoline_no_leak.phpt | 36 +++++++ 10 files changed, 327 insertions(+), 15 deletions(-) create mode 100644 ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline.phpt create mode 100644 ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline_no_leak.phpt diff --git a/NEWS b/NEWS index 38af4b7681d20..80bda686a1ba8 100644 --- a/NEWS +++ b/NEWS @@ -114,6 +114,7 @@ PHP NEWS - PDO_SQLITE: . throw on null bytes / resolve GH-13952 (divinity76). + . Implement GH-17321: Add setAuthorizer to Pdo\Sqlite. (nielsdos) - PGSQL: . Added pg_close_stmt to close a prepared statement while allowing diff --git a/UPGRADING b/UPGRADING index 2b7abad173c74..2ce2ba3c120b9 100644 --- a/UPGRADING +++ b/UPGRADING @@ -309,6 +309,11 @@ PHP 8.5 UPGRADE NOTES . Added enchant_dict_remove() to put a word on the exclusion list and remove it from the session dictionary. +- Pdo\Sqlite: + . Added support for Pdo\Sqlite::setAuthorizer(), which is the equivalent of + SQLite3::setAuthorizer(). The only interface difference is that the + pdo version returns void. + - PGSQL: . pg_close_stmt offers an alternative way to close a prepared statement from the DEALLOCATE sql command in that we can reuse diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index ff56d04049424..7661b36c5d314 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -332,6 +332,36 @@ PHP_METHOD(Pdo_Sqlite, openBlob) } } +PHP_METHOD(Pdo_Sqlite, setAuthorizer) +{ + zend_fcall_info fci; + zend_fcall_info_cache fcc; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC_NO_TRAMPOLINE_FREE_OR_NULL(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + + pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK_WITH_CLEANUP(free_fcc); + pdo_sqlite_db_handle *db_handle = (pdo_sqlite_db_handle *) dbh->driver_data; + + /* Clear previously set callback */ + if (ZEND_FCC_INITIALIZED(db_handle->authorizer_fcc)) { + zend_fcc_dtor(&db_handle->authorizer_fcc); + } + + /* Only enable userland authorizer if argument is not NULL */ + if (ZEND_FCI_INITIALIZED(fci)) { + zend_fcc_dup(&db_handle->authorizer_fcc, &fcc); + } + + return; + +free_fcc: + zend_release_fcall_info_cache(&fcc); + RETURN_THROWS(); +} + static int php_sqlite_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2) { @@ -349,7 +379,7 @@ static int php_sqlite_collation_callback(void *context, int string1_len, const v if (!Z_ISUNDEF(retval)) { if (Z_TYPE(retval) != IS_LONG) { zend_string *func_name = get_active_function_or_method_name(); - zend_type_error("%s(): Return value of the callback must be of type int, %s returned", + zend_type_error("%s(): Return value of the collation callback must be of type int, %s returned", ZSTR_VAL(func_name), zend_zval_value_name(&retval)); zend_string_release(func_name); zval_ptr_dtor(&retval); diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index e22c8ce10fccc..3832683598ed5 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -33,6 +33,16 @@ class Sqlite extends \PDO /** @cvalue PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES */ public const int ATTR_EXTENDED_RESULT_CODES = UNKNOWN; + /** @cvalue SQLITE_OK */ + public const int OK = UNKNOWN; + + /* Constants for authorizer return */ + + /** @cvalue SQLITE_DENY */ + public const int DENY = UNKNOWN; + /** @cvalue SQLITE_IGNORE */ + public const int IGNORE = UNKNOWN; + // Registers an aggregating User Defined Function for use in SQL statements public function createAggregate( string $name, @@ -63,4 +73,6 @@ public function openBlob( ?string $dbname = "main", int $flags = \Pdo\Sqlite::OPEN_READONLY ) {} + + public function setAuthorizer(?callable $callback): void {} } diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index 4abbc0bb625c6..75de256e55c7b 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7ceaf5fc8e9c92bf192e824084a706794395ce1a */ + * Stub hash: f8cd6b3c6aa662d76dca3d0a28d61acfb5a611b5 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Pdo_Sqlite_createAggregate, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -34,6 +34,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Pdo_Sqlite_openBlob, 0, 0, 3) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Pdo\\Sqlite::OPEN_READONLY") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Pdo_Sqlite_setAuthorizer, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1) +ZEND_END_ARG_INFO() + ZEND_METHOD(Pdo_Sqlite, createAggregate); ZEND_METHOD(Pdo_Sqlite, createCollation); ZEND_METHOD(Pdo_Sqlite, createFunction); @@ -41,6 +45,7 @@ ZEND_METHOD(Pdo_Sqlite, createFunction); ZEND_METHOD(Pdo_Sqlite, loadExtension); #endif ZEND_METHOD(Pdo_Sqlite, openBlob); +ZEND_METHOD(Pdo_Sqlite, setAuthorizer); static const zend_function_entry class_Pdo_Sqlite_methods[] = { ZEND_ME(Pdo_Sqlite, createAggregate, arginfo_class_Pdo_Sqlite_createAggregate, ZEND_ACC_PUBLIC) @@ -50,6 +55,7 @@ static const zend_function_entry class_Pdo_Sqlite_methods[] = { ZEND_ME(Pdo_Sqlite, loadExtension, arginfo_class_Pdo_Sqlite_loadExtension, ZEND_ACC_PUBLIC) #endif ZEND_ME(Pdo_Sqlite, openBlob, arginfo_class_Pdo_Sqlite_openBlob, ZEND_ACC_PUBLIC) + ZEND_ME(Pdo_Sqlite, setAuthorizer, arginfo_class_Pdo_Sqlite_setAuthorizer, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -104,5 +110,23 @@ static zend_class_entry *register_class_Pdo_Sqlite(zend_class_entry *class_entry zend_declare_typed_class_constant(class_entry, const_ATTR_EXTENDED_RESULT_CODES_name, &const_ATTR_EXTENDED_RESULT_CODES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_ATTR_EXTENDED_RESULT_CODES_name); + zval const_OK_value; + ZVAL_LONG(&const_OK_value, SQLITE_OK); + zend_string *const_OK_name = zend_string_init_interned("OK", sizeof("OK") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_OK_name, &const_OK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_OK_name); + + zval const_DENY_value; + ZVAL_LONG(&const_DENY_value, SQLITE_DENY); + zend_string *const_DENY_name = zend_string_init_interned("DENY", sizeof("DENY") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_DENY_name, &const_DENY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_DENY_name); + + zval const_IGNORE_value; + ZVAL_LONG(&const_IGNORE_value, SQLITE_IGNORE); + zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IGNORE_name); + return class_entry; } diff --git a/ext/pdo_sqlite/php_pdo_sqlite_int.h b/ext/pdo_sqlite/php_pdo_sqlite_int.h index 08d5f877ad520..4a39781f85c96 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite_int.h +++ b/ext/pdo_sqlite/php_pdo_sqlite_int.h @@ -50,6 +50,7 @@ typedef struct { pdo_sqlite_error_info einfo; struct pdo_sqlite_func *funcs; struct pdo_sqlite_collation *collations; + zend_fcall_info_cache authorizer_fcc; } pdo_sqlite_db_handle; typedef struct { diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 8a880a3425fba..ddf25d4965f06 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -97,6 +97,10 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H) { struct pdo_sqlite_func *func; + if (ZEND_FCC_INITIALIZED(H->authorizer_fcc)) { + zend_fcc_dtor(&H->authorizer_fcc); + } + while (H->funcs) { func = H->funcs; H->funcs = func->next; @@ -714,6 +718,10 @@ static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer) { pdo_sqlite_db_handle *H = dbh->driver_data; + if (ZEND_FCC_INITIALIZED(H->authorizer_fcc)) { + zend_get_gc_buffer_add_fcc(gc_buffer, &H->authorizer_fcc); + } + struct pdo_sqlite_func *func = H->funcs; while (func) { if (ZEND_FCC_INITIALIZED(func->func)) { @@ -784,24 +792,77 @@ static char *make_filename_safe(const char *filename) return estrdup(filename); } -static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4, - const char *arg5, const char *arg6) +#define ZVAL_NULLABLE_STRING(zv, str) do { \ + zval *zv_ = zv; \ + const char *str_ = str; \ + if (str_) { \ + ZVAL_STRING(zv_, str_); \ + } else { \ + ZVAL_NULL(zv_); \ + } \ +} while (0) + +static int authorizer(void *autharg, int access_type, const char *arg1, const char *arg2, + const char *arg3, const char *arg4) { - char *filename; - switch (access_type) { - case SQLITE_ATTACH: { - filename = make_filename_safe(arg3); + if (PG(open_basedir) && *PG(open_basedir)) { + if (access_type == SQLITE_ATTACH) { + char *filename = make_filename_safe(arg1); if (!filename) { return SQLITE_DENY; } efree(filename); - return SQLITE_OK; } + } - default: - /* access allowed */ - return SQLITE_OK; + pdo_sqlite_db_handle *db_obj = autharg; + + /* fallback to access allowed if authorizer callback is not defined */ + if (!ZEND_FCC_INITIALIZED(db_obj->authorizer_fcc)) { + return SQLITE_OK; + } + + /* call userland authorizer callback, if set */ + zval retval; + zval argv[5]; + + ZVAL_LONG(&argv[0], access_type); + ZVAL_NULLABLE_STRING(&argv[1], arg1); + ZVAL_NULLABLE_STRING(&argv[2], arg2); + ZVAL_NULLABLE_STRING(&argv[3], arg3); + ZVAL_NULLABLE_STRING(&argv[4], arg4); + + int authreturn = SQLITE_DENY; + + zend_call_known_fcc(&db_obj->authorizer_fcc, &retval, /* argc */ 5, argv, /* named_params */ NULL); + if (Z_ISUNDEF(retval)) { + ZEND_ASSERT(EG(exception)); + } else { + if (Z_TYPE(retval) != IS_LONG) { + zend_string *func_name = get_active_function_or_method_name(); + zend_type_error("%s(): Return value of the authorizer callback must be of type int, %s returned", + ZSTR_VAL(func_name), zend_zval_value_name(&retval)); + zend_string_release(func_name); + } else { + authreturn = Z_LVAL(retval); + + if (authreturn != SQLITE_OK && authreturn != SQLITE_IGNORE && authreturn != SQLITE_DENY) { + zend_string *func_name = get_active_function_or_method_name(); + zend_value_error("%s(): Return value of the authorizer callback must be one of Pdo\\Sqlite::OK, Pdo\\Sqlite::DENY, or Pdo\\Sqlite::IGNORE", + ZSTR_VAL(func_name)); + zend_string_release(func_name); + authreturn = SQLITE_DENY; + } + } } + + zval_ptr_dtor(&retval); + zval_ptr_dtor(&argv[1]); + zval_ptr_dtor(&argv[2]); + zval_ptr_dtor(&argv[3]); + zval_ptr_dtor(&argv[4]); + + return authreturn; } static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */ @@ -843,9 +904,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{ goto cleanup; } - if (PG(open_basedir) && *PG(open_basedir)) { - sqlite3_set_authorizer(H->db, authorizer, NULL); - } + sqlite3_set_authorizer(H->db, authorizer, H); if (driver_options) { timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout); diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer.phpt new file mode 100644 index 0000000000000..d1e9039ea1c4d --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer.phpt @@ -0,0 +1,101 @@ +--TEST-- +Pdo\Sqlite user authorizer callback +--EXTENSIONS-- +pdo_sqlite +--FILE-- +setAuthorizer(function (int $action) { + if ($action == 21 /* SELECT */) { + return Pdo\Sqlite::OK; + } + + return Pdo\Sqlite::DENY; +}); + +// This query should be accepted +var_dump($db->query('SELECT 1;')); + +try { + // This one should fail + var_dump($db->exec('CREATE TABLE test (a, b);')); +} catch (\Exception $e) { + echo $e->getMessage() . "\n"; +} + +// Test disabling the authorizer +$db->setAuthorizer(null); + +// This should now succeed +var_dump($db->exec('CREATE TABLE test (a); INSERT INTO test VALUES (42);')); +var_dump($db->exec('SELECT a FROM test;')); + +// Test if we are getting the correct arguments +$db->setAuthorizer(function (int $action) { + $constants = ["COPY", "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX", "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW", "CREATE_TRIGGER", "CREATE_VIEW", "DELETE", "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX", "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW", "DROP_TRIGGER", "DROP_VIEW", "INSERT", "PRAGMA", "READ", "SELECT", "TRANSACTION", "UPDATE"]; + + var_dump($constants[$action], implode(',', array_slice(func_get_args(), 1))); + return Pdo\Sqlite::OK; +}); + +var_dump($db->exec('SELECT * FROM test WHERE a = 42;')); +var_dump($db->exec('DROP TABLE test;')); + +// Try to return something invalid from the authorizer +$db->setAuthorizer(function () { + return 'FAIL'; +}); + +try { + var_dump($db->query('SELECT 1;')); +} catch (\Error $e) { + echo $e->getMessage() . "\n"; +} + +$db->setAuthorizer(function () { + return 4200; +}); + +try { + var_dump($db->query('SELECT 1;')); +} catch (\Error $e) { + echo $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +object(PDOStatement)#%d (1) { + ["queryString"]=> + string(9) "SELECT 1;" +} +SQLSTATE[HY000]: General error: 23 not authorized +int(1) +int(1) +string(6) "SELECT" +string(3) ",,," +string(4) "READ" +string(12) "test,a,main," +string(4) "READ" +string(12) "test,a,main," +int(1) +string(6) "DELETE" +string(20) "sqlite_master,,main," +string(10) "DROP_TABLE" +string(11) "test,,main," +string(6) "DELETE" +string(11) "test,,main," +string(6) "DELETE" +string(20) "sqlite_master,,main," +string(4) "READ" +string(28) "sqlite_master,tbl_name,main," +string(4) "READ" +string(24) "sqlite_master,type,main," +string(6) "UPDATE" +string(28) "sqlite_master,rootpage,main," +string(4) "READ" +string(28) "sqlite_master,rootpage,main," +int(1) +PDO::query(): Return value of the authorizer callback must be of type int, string returned +PDO::query(): Return value of the authorizer callback must be one of Pdo\Sqlite::OK, Pdo\Sqlite::DENY, or Pdo\Sqlite::IGNORE diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline.phpt new file mode 100644 index 0000000000000..c93a1f2e34a51 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline.phpt @@ -0,0 +1,43 @@ +--TEST-- +Pdo\Sqlite user authorizer trampoline callback +--EXTENSIONS-- +pdo_sqlite +--FILE-- +setAuthorizer($callback); + +// This query should be accepted +var_dump($db->query('SELECT 1;')); + +try { + // This one should fail + var_dump($db->query('CREATE TABLE test (a, b);')); +} catch (\Exception $e) { + echo $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +Trampoline for authorizer +object(PDOStatement)#%d (1) { + ["queryString"]=> + string(9) "SELECT 1;" +} +Trampoline for authorizer +SQLSTATE[HY000]: General error: 23 not authorized diff --git a/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline_no_leak.phpt b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline_no_leak.phpt new file mode 100644 index 0000000000000..84b83877b94a0 --- /dev/null +++ b/ext/pdo_sqlite/tests/subclasses/pdosqlite_setauthorizer_trampoline_no_leak.phpt @@ -0,0 +1,36 @@ +--TEST-- +PdoSqlite::setAuthorizer use F ZPP for trampoline callback and does not leak +--EXTENSIONS-- +pdo_sqlite +--FILE-- +newInstanceWithoutConstructor(); + +try { + var_dump($obj->setAuthorizer($callback)); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +DONE +--EXPECT-- +Invalid Pdo\Sqlite object: +Error: Pdo\Sqlite object is uninitialized +DONE From 685baf77df39083c033addf09106716989a1e69e Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sat, 19 Apr 2025 14:11:20 +0900 Subject: [PATCH 350/503] Fixed GH-17383 - pdo_firebird: PDOException has wrong code and message since PHP 8.4 (#18072) Closes #18072 Fixes #17383 --- .github/scripts/windows/test_task.bat | 5 +++- NEWS | 6 +++-- ext/pdo_firebird/firebird_driver.c | 3 ++- ext/pdo_firebird/tests/gh17383.phpt | 38 +++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 ext/pdo_firebird/tests/gh17383.phpt diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index 124b9b019ca4b..223d654300357 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -58,12 +58,15 @@ if "%PLATFORM%" == "x64" ( curl -sLo Firebird.zip %PHP_FIREBIRD_DOWNLOAD_URL% 7z x -oC:\Firebird Firebird.zip set PDO_FIREBIRD_TEST_DATABASE=C:\test.fdb -set PDO_FIREBIRD_TEST_DSN=firebird:dbname=%PDO_FIREBIRD_TEST_DATABASE% +set PDO_FIREBIRD_TEST_DSN=firebird:dbname=127.0.0.1:%PDO_FIREBIRD_TEST_DATABASE% set PDO_FIREBIRD_TEST_USER=SYSDBA set PDO_FIREBIRD_TEST_PASS=phpfi +echo create user %PDO_FIREBIRD_TEST_USER% password '%PDO_FIREBIRD_TEST_PASS%';> C:\Firebird\create_user.sql +echo commit;>> C:\Firebird\create_user.sql echo create database '%PDO_FIREBIRD_TEST_DATABASE%' user '%PDO_FIREBIRD_TEST_USER%' password '%PDO_FIREBIRD_TEST_PASS%';> C:\Firebird\setup.sql C:\Firebird\instsvc.exe install -n TestInstance C:\Firebird\isql -q -i C:\Firebird\setup.sql +C:\Firebird\isql -q -i C:\Firebird\create_user.sql -user sysdba %PDO_FIREBIRD_TEST_DATABASE% C:\Firebird\instsvc.exe start -n TestInstance if %errorlevel% neq 0 exit /b 3 path C:\Firebird;%PATH% diff --git a/NEWS b/NEWS index cd9bb021b9706..c3a3a69fd0867 100644 --- a/NEWS +++ b/NEWS @@ -42,8 +42,10 @@ PHP NEWS . Fix potential leaks when writing to BIO fails. (nielsdos) - PDO Firebird: - . Fixed GH-18276 - persistent connection - "zend_mm_heap corrupted" - with setAttribute() (SakiTakamachi). + . Fixed bug GH-18276 (persistent connection - "zend_mm_heap corrupted" + with setAttribute()) (SakiTakamachi). + . Fixed bug GH-17383 (PDOException has wrong code and message since PHP 8.4) + (SakiTakamachi). - PDO Sqlite: . Fix memory leak on error return of collation callback. (nielsdos) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 367d6a746b3ae..259ed53af98a8 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -594,7 +594,8 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ } H->in_manually_txn = 0; - if (isc_detach_database(H->isc_status, &H->db)) { + /* isc_detach_database returns 0 on success, 1 on failure. */ + if (H->db && isc_detach_database(H->isc_status, &H->db)) { php_firebird_error(dbh); } diff --git a/ext/pdo_firebird/tests/gh17383.phpt b/ext/pdo_firebird/tests/gh17383.phpt new file mode 100644 index 0000000000000..6adad311938c6 --- /dev/null +++ b/ext/pdo_firebird/tests/gh17383.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-17383 (PDOException has wrong code and message since PHP 8.4) +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--XLEAK-- +A bug in firebird causes a memory leak when calling `isc_attach_database()`. +See https://github.com/FirebirdSQL/firebird/issues/7849 +--FILE-- +getCode() . "\n"; + echo 'PDOException message: ' . $e->getMessage() . "\n"; + echo "\n"; + } +} +?> +--EXPECT-- +PDOException code: 335544721 +PDOException message: SQLSTATE[HY000] [335544721] Unable to complete network request to host "invalid_host". + +PDOException code: 335544472 +PDOException message: SQLSTATE[HY000] [335544472] Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + +PDOException code: 335544472 +PDOException message: SQLSTATE[HY000] [335544472] Your user name and password are not defined. Ask your database administrator to set up a Firebird login. From ba83d5daebe0ed425b3dccac356a523423ec4972 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 19 Apr 2025 10:18:53 +0100 Subject: [PATCH 351/503] sapi/litespeed and ext/standard: Fix few build warnings. (#18265) --- ext/standard/exec.c | 2 +- ext/standard/mail.c | 2 +- sapi/litespeed/lsapi_main.c | 8 ++++---- sapi/litespeed/lscriu.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/standard/exec.c b/ext/standard/exec.c index 1df46cc050b01..ce3e8565ad200 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -118,7 +118,7 @@ PHPAPI int php_exec(int type, const char *cmd, zval *array, zval *return_value) php_stream *stream; size_t buflen, bufl = 0; #if PHP_SIGCHILD - void (*sig_handler)() = signal(SIGCHLD, SIG_DFL); + void (*sig_handler)(int) = signal(SIGCHLD, SIG_DFL); #endif #ifdef PHP_WIN32 diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 35c23a0be76c0..0243ec897a05e 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -445,7 +445,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c const char *hdr = headers; char *ahdr = NULL; #if PHP_SIGCHILD - void (*sig_handler)() = NULL; + void (*sig_handler)(int) = NULL; #endif #define MAIL_RET(val) \ diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index 259d4a985cc66..a135e031b24d0 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -1678,11 +1678,11 @@ PHP_FUNCTION(litespeed_response_headers) char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH]; if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + RETURN_THROWS(); + } - if (!&SG(sapi_headers).headers) { - RETURN_FALSE; + if (!zend_llist_count(&SG(sapi_headers).headers)) { + RETURN_FALSE; } array_init(return_value); diff --git a/sapi/litespeed/lscriu.c b/sapi/litespeed/lscriu.c index 1eb468fdf28cc..409fe989b5551 100644 --- a/sapi/litespeed/lscriu.c +++ b/sapi/litespeed/lscriu.c @@ -658,7 +658,7 @@ static int LSCRIU_Init_Env_Parameters(void) } -void LSCRIU_inc_req_processed() +void LSCRIU_inc_req_processed(void) { if (!LSCRIU_Get_Global_Counter_Type()) { ++s_requests_count; From fcd0f72cdd06728d1276419d77ca079c0789af48 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 18 Apr 2025 19:10:23 +0100 Subject: [PATCH 352/503] GH-18345: adding Locale::isRightToLeft. Checks is the locale is written left to right. It makes sure all the needed likely subtags are included (maximization) then determines the direction by known matches. close GH-18351 --- NEWS | 2 ++ UPGRADING | 4 ++++ ext/intl/locale/locale.stub.php | 5 +++++ ext/intl/locale/locale_arginfo.h | 8 +++++++- ext/intl/locale/locale_methods.c | 16 ++++++++++++++++ ext/intl/php_intl.stub.php | 2 ++ ext/intl/php_intl_arginfo.h | 8 +++++++- ext/intl/tests/locale_is_right_to_left.phpt | 16 ++++++++++++++++ 8 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 ext/intl/tests/locale_is_right_to_left.phpt diff --git a/NEWS b/NEWS index 80bda686a1ba8..47bf820d6b64c 100644 --- a/NEWS +++ b/NEWS @@ -85,6 +85,8 @@ PHP NEWS with uninitialised classes or clone failure. (David Carlier) . Added DECIMAL_COMPACT_SHORT/DECIMAL_COMPACT_LONG for NumberFormatter class. (BogdanUngureanu) + . Added Locale::isRightToLeft to check if a locale is written right to left. + (David Carlier) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 2ce2ba3c120b9..6b6c555adcf73 100644 --- a/UPGRADING +++ b/UPGRADING @@ -309,6 +309,10 @@ PHP 8.5 UPGRADE NOTES . Added enchant_dict_remove() to put a word on the exclusion list and remove it from the session dictionary. +- Intl: + . Added locale_is_right_to_left/Locale::isRightToLeft, returns true if + the locale is written right to left (after its enrichment with likely subtags). + - Pdo\Sqlite: . Added support for Pdo\Sqlite::setAuthorizer(), which is the equivalent of SQLite3::setAuthorizer(). The only interface difference is that the diff --git a/ext/intl/locale/locale.stub.php b/ext/intl/locale/locale.stub.php index 1ec2af308edd2..fcda8f68409ce 100644 --- a/ext/intl/locale/locale.stub.php +++ b/ext/intl/locale/locale.stub.php @@ -133,4 +133,9 @@ public static function canonicalize(string $locale): ?string {} * @alias locale_accept_from_http */ public static function acceptFromHttp(string $header): string|false {} + + /** + * @alias locale_is_right_to_left + */ + public static function isRightToLeft(string $locale): bool {} } diff --git a/ext/intl/locale/locale_arginfo.h b/ext/intl/locale/locale_arginfo.h index 7bba882d20457..40426a1aa9e78 100644 --- a/ext/intl/locale/locale_arginfo.h +++ b/ext/intl/locale/locale_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 59861342e0075231d2a576afb2d5df6973d70684 */ + * Stub hash: f09cfd61f3e20576c7f6d5da17a6d9c009d6ab64 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Locale_getDefault, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -62,6 +62,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Locale_acceptFro ZEND_ARG_TYPE_INFO(0, header, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Locale_isRightToLeft, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(locale_get_default); ZEND_FUNCTION(locale_set_default); ZEND_FUNCTION(locale_get_primary_language); @@ -80,6 +84,7 @@ ZEND_FUNCTION(locale_filter_matches); ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_accept_from_http); +ZEND_FUNCTION(locale_is_right_to_left); static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("getDefault", zif_locale_get_default, arginfo_class_Locale_getDefault, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) @@ -100,6 +105,7 @@ static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("lookup", zif_locale_lookup, arginfo_class_Locale_lookup, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("canonicalize", zif_locale_canonicalize, arginfo_class_Locale_canonicalize, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("acceptFromHttp", zif_locale_accept_from_http, arginfo_class_Locale_acceptFromHttp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) + ZEND_RAW_FENTRY("isRightToLeft", zif_locale_is_right_to_left, arginfo_class_Locale_isRightToLeft, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_FE_END }; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index b2891de9d4aca..bba52a90994cc 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1619,3 +1619,19 @@ PHP_FUNCTION(locale_accept_from_http) RETURN_STRINGL(resultLocale, len); } /* }}} */ + +PHP_FUNCTION(locale_is_right_to_left) +{ + char *locale; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + RETURN_BOOL(uloc_isRightToLeft(locale)); +} diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index f3a80dd511943..4469845483e8e 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -501,6 +501,8 @@ function locale_lookup(array $languageTag, string $locale, bool $canonicalize = function locale_accept_from_http(string $header): string|false {} +function locale_is_right_to_left(string $locale): bool {} + /* msgformat */ function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index 11c585d8df63b..bf016abf99dcb 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 168eabfdcbf29189f2327448f104ea98752d1c5a */ + * Stub hash: 4fb44fc170e74af2e9fb52c5a1029004f708fcda */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") @@ -566,6 +566,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_locale_accept_from_http, 0, 1, M ZEND_ARG_TYPE_INFO(0, header, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_locale_is_right_to_left, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_msgfmt_create, 0, 2, MessageFormatter, 1) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) @@ -920,6 +924,7 @@ ZEND_FUNCTION(locale_filter_matches); ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_accept_from_http); +ZEND_FUNCTION(locale_is_right_to_left); ZEND_FUNCTION(msgfmt_create); ZEND_FUNCTION(msgfmt_format); ZEND_FUNCTION(msgfmt_format_message); @@ -1107,6 +1112,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(locale_canonicalize, arginfo_locale_canonicalize) ZEND_FE(locale_lookup, arginfo_locale_lookup) ZEND_FE(locale_accept_from_http, arginfo_locale_accept_from_http) + ZEND_FE(locale_is_right_to_left, arginfo_locale_is_right_to_left) ZEND_FE(msgfmt_create, arginfo_msgfmt_create) ZEND_FE(msgfmt_format, arginfo_msgfmt_format) ZEND_FE(msgfmt_format_message, arginfo_msgfmt_format_message) diff --git a/ext/intl/tests/locale_is_right_to_left.phpt b/ext/intl/tests/locale_is_right_to_left.phpt new file mode 100644 index 0000000000000..c586582d42225 --- /dev/null +++ b/ext/intl/tests/locale_is_right_to_left.phpt @@ -0,0 +1,16 @@ +--TEST-- +locale_is_right_to_left +--EXTENSIONS-- +intl +--FILE-- + +--EXPECT-- +bool(false) +bool(false) +bool(false) +bool(true) From 25f4f7982cb3b6620befd9ed4861792192d986a1 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Sat, 19 Apr 2025 13:26:09 +0100 Subject: [PATCH 353/503] Drop unused variables (#18023) --- ext/mysqlnd/mysqlnd_auth.c | 4 ---- ext/mysqlnd/mysqlnd_commands.c | 3 --- ext/mysqlnd/mysqlnd_connection.c | 21 ++++----------------- ext/mysqlnd/mysqlnd_structs.h | 5 ----- 4 files changed, 4 insertions(+), 29 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index 3a30b1458dea0..b8a23f87c663e 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -487,10 +487,6 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn, } } if (ret == PASS) { - ZEND_ASSERT(conn->username.s != user && conn->password.s != passwd); - mysqlnd_set_persistent_string(&conn->username, user, user_len, conn->persistent); - mysqlnd_set_persistent_string(&conn->password, passwd, passwd_len, conn->persistent); - mysqlnd_set_string(&conn->last_message, NULL, 0); UPSERT_STATUS_RESET(conn->upsert_status); /* set charset for old servers */ diff --git a/ext/mysqlnd/mysqlnd_commands.c b/ext/mysqlnd/mysqlnd_commands.c index 27a5f13a30746..52731425e1808 100644 --- a/ext/mysqlnd/mysqlnd_commands.c +++ b/ext/mysqlnd/mysqlnd_commands.c @@ -107,9 +107,6 @@ MYSQLND_METHOD(mysqlnd_command, init_db)(MYSQLND_CONN_DATA * const conn, const M a protocol of giving back -1. Thus we have to follow it :( */ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); - if (ret == PASS) { - mysqlnd_set_persistent_string(&conn->connect_or_select_db, db.s, db.l, conn->persistent); - } DBG_RETURN(ret); } diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 2787b32931747..42acb258665bc 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -282,11 +282,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn) DBG_INF("Freeing memory of members"); - mysqlnd_set_persistent_string(&conn->hostname, NULL, 0, pers); - mysqlnd_set_persistent_string(&conn->username, NULL, 0, pers); - mysqlnd_set_persistent_string(&conn->password, NULL, 0, pers); - mysqlnd_set_persistent_string(&conn->connect_or_select_db, NULL, 0, pers); - mysqlnd_set_persistent_string(&conn->unix_socket, NULL, 0, pers); DBG_INF_FMT("scheme=%s", conn->scheme.s); mysqlnd_set_persistent_string(&conn->scheme, NULL, 0, pers); @@ -658,22 +653,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, if (transport.s) { mnd_sprintf_free(transport.s); transport.s = NULL; - } - - if (!conn->scheme.s) { + } else { goto err; /* OOM */ } - mysqlnd_set_persistent_string(&conn->username, username.s, username.l, conn->persistent); - mysqlnd_set_persistent_string(&conn->password, username.s, password.l, conn->persistent); conn->port = port; - mysqlnd_set_persistent_string(&conn->connect_or_select_db, database.s, database.l, conn->persistent); if (!unix_socket && !named_pipe) { - mysqlnd_set_persistent_string(&conn->hostname, hostname.s, hostname.l, conn->persistent); { char *p; - mnd_sprintf(&p, 0, "%s via TCP/IP", conn->hostname.s); + mnd_sprintf(&p, 0, "%s via TCP/IP", hostname.s); if (!p) { SET_OOM_ERROR(conn->error_info); goto err; /* OOM */ @@ -682,12 +671,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, mnd_sprintf_free(p); } } else { - conn->unix_socket.s = mnd_pestrdup(socket_or_pipe.s, conn->persistent); if (unix_socket) { conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent); } else if (named_pipe) { char *p; - mnd_sprintf(&p, 0, "%s via named pipe", conn->unix_socket.s); + mnd_sprintf(&p, 0, "%s via named pipe", socket_or_pipe.s); if (!p) { SET_OOM_ERROR(conn->error_info); goto err; /* OOM */ @@ -697,11 +685,10 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, } else { php_error_docref(NULL, E_WARNING, "Impossible. Should be either socket or a pipe. Report a bug!"); } - if (!conn->unix_socket.s || !conn->host_info) { + if (!socket_or_pipe.s || !conn->host_info) { SET_OOM_ERROR(conn->error_info); goto err; /* OOM */ } - conn->unix_socket.l = strlen(conn->unix_socket.s); } SET_EMPTY_ERROR(conn->error_info); diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index b0c9f3a37d6e2..9cbbf4a64f144 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -890,10 +890,6 @@ struct st_mysqlnd_connection_data MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory; /* Information related */ - MYSQLND_STRING hostname; - MYSQLND_STRING unix_socket; - MYSQLND_STRING username; - MYSQLND_STRING password; MYSQLND_STRING scheme; uint64_t thread_id; char *server_version; @@ -901,7 +897,6 @@ struct st_mysqlnd_connection_data MYSQLND_STRING authentication_plugin_data; const MYSQLND_CHARSET *charset; const MYSQLND_CHARSET *greet_charset; - MYSQLND_STRING connect_or_select_db; MYSQLND_INFILE infile; unsigned int protocol_version; unsigned int port; From 2e7df9e4238f2aff421eb09d841381675d073a24 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 19 Apr 2025 16:27:14 +0100 Subject: [PATCH 354/503] ext/gd: imagefilter* using overflow checks. (#18283) Accept up to UINT_MAX * sizeof(int) colors. --- ext/gd/gd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 9017d58bd75aa..c993860f3b47e 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3599,7 +3599,7 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS) RETURN_BOOL(gdImageScatter(im, (int)scatter_sub, (int)scatter_plus)); } - colors = emalloc(num_colors * sizeof(int)); + colors = safe_emalloc(num_colors, sizeof(int), 0); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hash_colors), color) { *(colors + i++) = (int) zval_get_long(color); From 91a310e6035cb01176b955f7bdbeb288c7e1258c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 19 Apr 2025 17:59:48 +0200 Subject: [PATCH 355/503] Get rid of separate DOM HashPosition member (#18354) Besides the fact that this is only used for DOM_NODESET and thus makes no sense of being on the iterator itself, it's also redundant now that we have the index member. --- ext/dom/dom_iterators.c | 13 +++++-------- ext/dom/php_dom.h | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index e292728de271d..a0797967d1e76 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -189,9 +189,8 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */ objmap->nodetype != XML_NOTATION_NODE) { if (objmap->nodetype == DOM_NODESET) { HashTable *nodeht = Z_ARRVAL_P(&objmap->baseobj_zv); - zval *entry; - zend_hash_move_forward_ex(nodeht, &iterator->pos); - if ((entry = zend_hash_get_current_data_ex(nodeht, &iterator->pos))) { + zval *entry = zend_hash_index_find(nodeht, iterator->index); + if (entry) { zval_ptr_dtor(&iterator->curobj); ZVAL_COPY(&iterator->curobj, entry); return; @@ -263,8 +262,6 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i dom_object *intern; dom_nnodemap_object *objmap; xmlNodePtr curnode=NULL; - HashTable *nodeht; - zval *entry; php_dom_iterator *iterator; if (by_ref) { @@ -284,9 +281,9 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i if (objmap->nodetype != XML_ENTITY_NODE && objmap->nodetype != XML_NOTATION_NODE) { if (objmap->nodetype == DOM_NODESET) { - nodeht = Z_ARRVAL_P(&objmap->baseobj_zv); - zend_hash_internal_pointer_reset_ex(nodeht, &iterator->pos); - if ((entry = zend_hash_get_current_data_ex(nodeht, &iterator->pos))) { + HashTable *nodeht = Z_ARRVAL_P(&objmap->baseobj_zv); + zval *entry = zend_hash_index_find(nodeht, 0); + if (entry) { ZVAL_COPY(&iterator->curobj, entry); } } else { diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 438857305db66..31fec5a7cabcb 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -97,7 +97,6 @@ typedef struct dom_nnodemap_object { typedef struct { zend_object_iterator intern; zval curobj; - HashPosition pos; /* intern->index is only updated for FE_* opcodes, not for e.g. unpacking, * yet we need to track the position of the node relative to the start. */ zend_ulong index; From 35e96f621b7b4d257efa612b497972f0a057a430 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 19 Apr 2025 16:00:06 +0200 Subject: [PATCH 356/503] DOM/XPath: Use ZSTR_LEN abstraction instead of direct member access --- ext/dom/xpath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index c6f8053d1a3bf..de7ce22ed1285 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -527,7 +527,7 @@ PHP_METHOD(DOMXPath, quote) { smart_str_appendc(&output, ','); } ZEND_ASSERT(ptr == end); - ZSTR_VAL(output.s)[output.s->len - 1] = ')'; + ZSTR_VAL(output.s)[ZSTR_LEN(output.s) - 1] = ')'; RETURN_STR(smart_str_extract(&output)); } } From f39c07a3bbe52cc1e497eed70e0d7f7d70113fed Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 19 Apr 2025 16:01:34 +0200 Subject: [PATCH 357/503] DOM/XPath: Use RETURN_NEW_STR These strings are newly allocated and can't be interned, so we can use RETURN_NEW_STR. --- ext/dom/xpath.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index de7ce22ed1285..8707af1fa94cf 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -499,14 +499,14 @@ PHP_METHOD(DOMXPath, quote) { memcpy(ZSTR_VAL(output) + 1, input, input_len); ZSTR_VAL(output)[input_len + 1] = '\''; ZSTR_VAL(output)[input_len + 2] = '\0'; - RETURN_STR(output); + RETURN_NEW_STR(output); } else if (memchr(input, '"', input_len) == NULL) { zend_string *const output = zend_string_safe_alloc(1, input_len, 2, false); ZSTR_VAL(output)[0] = '"'; memcpy(ZSTR_VAL(output) + 1, input, input_len); ZSTR_VAL(output)[input_len + 1] = '"'; ZSTR_VAL(output)[input_len + 2] = '\0'; - RETURN_STR(output); + RETURN_NEW_STR(output); } else { smart_str output = {0}; // need to use the concat() trick published by Robert Rossney at https://stackoverflow.com/a/1352556/1067003 @@ -528,7 +528,7 @@ PHP_METHOD(DOMXPath, quote) { } ZEND_ASSERT(ptr == end); ZSTR_VAL(output.s)[ZSTR_LEN(output.s) - 1] = ')'; - RETURN_STR(smart_str_extract(&output)); + RETURN_NEW_STR(smart_str_extract(&output)); } } /* }}} */ From dc9039086c74deab30f94312cf3f028af749b642 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 20 Apr 2025 02:30:25 +0200 Subject: [PATCH 358/503] Avoid pointless refcounting in php_intl_idn_to_46() --- ext/intl/idn/idn.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c index 62ee83f62f9ba..a0ea0795bf563 100644 --- a/ext/intl/idn/idn.c +++ b/ext/intl/idn/idn.c @@ -90,12 +90,6 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, ZSTR_VAL(buffer)[len] = '\0'; ZSTR_LEN(buffer) = len; - if (info.errors == 0) { - RETVAL_STR_COPY(buffer); - } else { - RETVAL_FALSE; - } - if (idna_info) { add_assoc_str_ex(idna_info, "result", sizeof("result")-1, zend_string_copy(buffer)); add_assoc_bool_ex(idna_info, "isTransitionalDifferent", @@ -103,7 +97,13 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (zend_long)info.errors); } - zend_string_release(buffer); + if (info.errors == 0) { + RETVAL_STR(buffer); + } else { + zend_string_release_ex(buffer, false); + RETVAL_FALSE; + } + uidna_close(uts46); } From 68b904884b5dca7e217aaed77852f7308c1140e7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 20 Apr 2025 02:31:15 +0200 Subject: [PATCH 359/503] Factor out duplicated code --- ext/intl/idn/idn.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c index a0ea0795bf563..cd4546ad7f8bb 100644 --- a/ext/intl/idn/idn.c +++ b/ext/intl/idn/idn.c @@ -57,6 +57,7 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, UErrorCode status = U_ZERO_ERROR; UIDNA *uts46; int32_t len; + int32_t buffer_capac; zend_string *buffer; UIDNAInfo info = UIDNA_INFO_INITIALIZER; @@ -66,25 +67,20 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, } if (mode == INTL_IDN_TO_ASCII) { - const int32_t buffer_capac = 255; + buffer_capac = 255; buffer = zend_string_alloc(buffer_capac, 0); len = uidna_nameToASCII_UTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), ZSTR_VAL(buffer), buffer_capac, &info, &status); - if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { - uidna_close(uts46); - zend_string_efree(buffer); - RETURN_FALSE; - } } else { - const int32_t buffer_capac = 252*4; + buffer_capac = 252*4; buffer = zend_string_alloc(buffer_capac, 0); len = uidna_nameToUnicodeUTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), ZSTR_VAL(buffer), buffer_capac, &info, &status); - if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { - uidna_close(uts46); - zend_string_efree(buffer); - RETURN_FALSE; - } + } + if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { + uidna_close(uts46); + zend_string_efree(buffer); + RETURN_FALSE; } ZSTR_VAL(buffer)[len] = '\0'; From e9b01f202b13e8644ab19a2909b8ab9d2a8ca706 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 20 Apr 2025 02:21:04 +0200 Subject: [PATCH 360/503] Use pre-allocated array sizes and packed where possible in intl --- ext/intl/collator/collator_sort.c | 3 ++- ext/intl/converter/converter.c | 12 ++++++++---- ext/intl/msgformat/msgformat_parse.c | 3 ++- ext/intl/resourcebundle/resourcebundle.c | 3 ++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c index c28ffb82cf737..75466aacb07af 100644 --- a/ext/intl/collator/collator_sort.c +++ b/ext/intl/collator/collator_sort.c @@ -469,7 +469,8 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) ZVAL_COPY_VALUE(&garbage, array); /* for resulting hash we'll assign new hash keys rather then reordering */ - array_init(array); + array_init_size(array, sortKeyCount); + zend_hash_real_init_packed(Z_ARRVAL_P(array)); for( j = 0; j < sortKeyCount; j++ ) { diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c index 73a7cb573134a..3aa7a53aa485b 100644 --- a/ext/intl/converter/converter.c +++ b/ext/intl/converter/converter.c @@ -294,7 +294,8 @@ static void php_converter_from_u_callback(const void *context, zval zargs[4]; ZVAL_LONG(&zargs[0], reason); - array_init(&zargs[1]); + array_init_size(&zargs[1], length); + zend_hash_real_init_packed(Z_ARRVAL(zargs[1])); int i = 0; while (i < length) { UChar32 c; @@ -807,7 +808,8 @@ PHP_METHOD(UConverter, getAvailable) { intl_error_reset(NULL); - array_init(return_value); + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for(i = 0; i < count; i++) { const char *name = ucnv_getAvailableName(i); add_next_index_string(return_value, name); @@ -833,7 +835,8 @@ PHP_METHOD(UConverter, getAliases) { RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for(i = 0; i < count; i++) { const char *alias; @@ -856,8 +859,9 @@ PHP_METHOD(UConverter, getStandards) { ZEND_PARSE_PARAMETERS_NONE(); intl_error_reset(NULL); - array_init(return_value); count = ucnv_countStandards(); + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for(i = 0; i < count; i++) { UErrorCode error = U_ZERO_ERROR; const char *name = ucnv_getStandard(i, &error); diff --git a/ext/intl/msgformat/msgformat_parse.c b/ext/intl/msgformat/msgformat_parse.c index c55671cf856a6..80ede995c42e7 100644 --- a/ext/intl/msgformat/msgformat_parse.c +++ b/ext/intl/msgformat/msgformat_parse.c @@ -42,7 +42,8 @@ static void msgfmt_do_parse(MessageFormatter_object *mfo, char *source, size_t s } INTL_METHOD_CHECK_STATUS(mfo, "Parsing failed"); - array_init(return_value); + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for(i=0;ichild, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve vector value"); - array_init( return_value ); + array_init_size( return_value, ilen ); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i=0; i Date: Sun, 20 Apr 2025 12:25:45 +0200 Subject: [PATCH 361/503] Fix reference support for intltz_get_offset() It should use the helper macros such that types are properly respected. Closes GH-18364. --- NEWS | 3 +++ .../tests/intltz_get_offset_references.phpt | 26 +++++++++++++++++++ ext/intl/timezone/timezone_methods.cpp | 8 +++--- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 ext/intl/tests/intltz_get_offset_references.phpt diff --git a/NEWS b/NEWS index ac31131ea9d22..55a58a4d8e78f 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,9 @@ PHP NEWS . Fixed GH-18243 imagettftext() overflow/underflow on font size value. (David Carlier) +- Intl: + . Fix reference support for intltz_get_offset(). (nielsdos) + - LDAP: . Fixed bug GH-17776 (LDAP_OPT_X_TLS_* options can't be overridden). (Remi) . Fix NULL deref on high modification key. (nielsdos) diff --git a/ext/intl/tests/intltz_get_offset_references.phpt b/ext/intl/tests/intltz_get_offset_references.phpt new file mode 100644 index 0000000000000..6f104863d2212 --- /dev/null +++ b/ext/intl/tests/intltz_get_offset_references.phpt @@ -0,0 +1,26 @@ +--TEST-- +intltz_get_offset references +--EXTENSIONS-- +intl +--FILE-- +a = $test->b = "hello"; + +$rawOffset =& $test->a; +$dstOffset =& $test->b; +intltz_get_offset($tz, 0.0, true, $rawOffset, $dstOffset); +var_dump($test); +?> +--EXPECT-- +object(Test)#2 (2) { + ["a"]=> + &string(7) "3600000" + ["b"]=> + &string(1) "0" +} diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index cae64026fa5db..580a721e79ec1 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -419,7 +419,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_offset) TIMEZONE_METHOD_INIT_VARS; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Odbz/z/", &object, TimeZone_ce_ptr, &date, &local, &rawOffsetArg, + "Odbzz", &object, TimeZone_ce_ptr, &date, &local, &rawOffsetArg, &dstOffsetArg) == FAILURE) { RETURN_THROWS(); } @@ -431,10 +431,8 @@ U_CFUNC PHP_FUNCTION(intltz_get_offset) INTL_METHOD_CHECK_STATUS(to, "intltz_get_offset: error obtaining offset"); - zval_ptr_dtor(rawOffsetArg); - ZVAL_LONG(rawOffsetArg, rawOffset); - zval_ptr_dtor(dstOffsetArg); - ZVAL_LONG(dstOffsetArg, dstOffset); + ZEND_TRY_ASSIGN_REF_LONG(rawOffsetArg, rawOffset); + ZEND_TRY_ASSIGN_REF_LONG(dstOffsetArg, dstOffset); RETURN_TRUE; } From 2c3a2da48acee059d6666b82d1fb03e804754416 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 20 Apr 2025 17:30:12 +0100 Subject: [PATCH 362/503] ext/gd: array supplied to user optimisations. (#18366) explictly allocate packed arrays when it applies. --- ext/gd/gd.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index c993860f3b47e..e993fb65f47d0 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -2438,7 +2438,7 @@ PHP_FUNCTION(imagecolorsforindex) col = index; if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) { - array_init(return_value); + array_init_size(return_value, 4); add_assoc_long(return_value,"red", gdImageRed(im,col)); add_assoc_long(return_value,"green", gdImageGreen(im,col)); @@ -3303,11 +3303,12 @@ PHP_FUNCTION(imagegetclip) gdImageGetClip(im, &x1, &y1, &x2, &y2); - array_init(return_value); - add_next_index_long(return_value, x1); - add_next_index_long(return_value, y1); - add_next_index_long(return_value, x2); - add_next_index_long(return_value, y2); + array_init_size(return_value, 4); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + add_index_long(return_value, 0, x1); + add_index_long(return_value, 1, y1); + add_index_long(return_value, 2, x2); + add_index_long(return_value, 3, y2); } /* }}} */ @@ -3398,11 +3399,12 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode) RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, 8); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); /* return array with the text's bounding box */ for (i = 0; i < 8; i++) { - add_next_index_long(return_value, brect[i]); + add_index_long(return_value, i, brect[i]); } } /* }}} */ @@ -4130,7 +4132,8 @@ PHP_FUNCTION(imageaffinematrixget) if (res == GD_FALSE) { RETURN_FALSE; } else { - array_init(return_value); + array_init_size(return_value, 6); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (uint8_t i = 0; i < 6; i++) { add_index_double(return_value, i, affine[i]); } @@ -4196,7 +4199,8 @@ PHP_FUNCTION(imageaffinematrixconcat) RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, 6); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i = 0; i < 6; i++) { add_index_double(return_value, i, mr[i]); } @@ -4288,9 +4292,10 @@ PHP_FUNCTION(imageresolution) RETURN_TRUE; } - array_init(return_value); - add_next_index_long(return_value, gdImageResolutionX(im)); - add_next_index_long(return_value, gdImageResolutionY(im)); + zval imx, imy; + ZVAL_LONG(&imx, gdImageResolutionX(im)); + ZVAL_LONG(&imy, gdImageResolutionY(im)); + RETURN_ARR(zend_new_pair(&imx, &imy)); } /* }}} */ From 68d54030a1322f2b2912f08f1149204ca137cd81 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 20 Apr 2025 19:34:11 +0100 Subject: [PATCH 363/503] ext/sockets: using array optimisations. (#18367) mostly explicit packed arrays. --- ext/sockets/conversions.c | 1 + ext/sockets/sockets.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index dd3b018c98d72..1f34e6601d4dc 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -1024,6 +1024,7 @@ static void to_zval_read_control_array(const char *msghdr_c, zval *zv, res_conte uint32_t i = 1; array_init(zv); + zend_hash_real_init_packed(Z_ARRVAL_P(zv)); for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL && !ctx->err.has_error; diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 68674120892b6..2d8b55c6b97ba 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -1973,6 +1973,7 @@ PHP_FUNCTION(socket_get_option) size_t arrlen = optlen / sizeof(struct fil_info); array_init_size(return_value, arrlen); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i = 0; i < arrlen; i++) { add_index_string(return_value, i, fi[i].fi_name); @@ -2373,7 +2374,7 @@ PHP_FUNCTION(socket_create_pair) RETURN_FALSE; } - fds_array_zval = zend_try_array_init(fds_array_zval); + fds_array_zval = zend_try_array_init_size(fds_array_zval, 2); if (!fds_array_zval) { zval_ptr_dtor(&retval[0]); zval_ptr_dtor(&retval[1]); @@ -2776,6 +2777,7 @@ PHP_FUNCTION(socket_addrinfo_lookup) } array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (rp = result; rp != NULL; rp = rp->ai_next) { if (rp->ai_family != AF_UNSPEC) { From b385e0dd2b54cc914b1fa707d6e3cbff794b4806 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 20 Apr 2025 23:23:43 +0100 Subject: [PATCH 364/503] ext/posix: preallocate arrays and/or change to packed ones. (#18370) --- ext/posix/posix.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index d465e5230938a..68d47840c5e20 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -236,10 +236,11 @@ PHP_FUNCTION(posix_getgroups) RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, result); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i=0; igr_name); if (g->gr_passwd) { @@ -1174,7 +1176,8 @@ PHP_FUNCTION(posix_getrlimit) RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, 2); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); if (rl.rlim_cur == RLIM_INFINITY) { add_next_index_stringl(return_value, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1); } else { From 158181ff378e3a90bf7d5a43b39ec2d7288dde0c Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 20 Apr 2025 23:23:56 +0100 Subject: [PATCH 365/503] ext/pcntl: pcntl_sigprocmask/pcntl_getcpuaffinity to packed arrays. (#18369) --- ext/pcntl/pcntl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 8db1d10c698c8..2189f94c992f5 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -956,6 +956,7 @@ PHP_FUNCTION(pcntl_sigprocmask) RETURN_THROWS(); } + zend_hash_real_init_packed(Z_ARRVAL_P(user_old_set)); for (unsigned int signal_no = 1; signal_no < PCNTL_G(num_signals); ++signal_no) { if (sigismember(&old_set, signal_no) != 1) { continue; @@ -1680,6 +1681,7 @@ PHP_FUNCTION(pcntl_getcpuaffinity) zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_CONF); array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (zend_ulong i = 0; i < maxcpus; i ++) { if (PCNTL_CPU_ISSET(i, mask)) { From 1a1a83f1fc7dd5d63da57b06922b692da65cd5c1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 14 Apr 2025 07:18:31 -0700 Subject: [PATCH 366/503] Fix GH-18136: tracing JIT floating point register clobbering on Windows and ARM64 On win64, xmm6-xmm15 are preserved registers, but the prologues and epilogues of JITted code don't handle these. The issue occurs when calling into the JIT code again via an internal handler (like call_user_func). Therefore, we want to save/restore xmm registers upon entering/leaving execute_ex. Since MSVC x64 does not support inline assembly, we create an assembly wrapper around the real execute_ex function. The alternative is to always save/restore these xmm registers into the fixed call frame, but this causes unnecessary overhead. The same issue occurs for ARM64 platforms for floating point register 8 to 15. However, there we can use inline asm to fix this. Closes GH-18352. --- NEWS | 2 ++ Zend/asm/save_xmm_x86_64_ms_masm.asm | 43 ++++++++++++++++++++++++++++ Zend/zend_vm_execute.h | 9 ++++++ Zend/zend_vm_execute.skl | 9 ++++++ ext/opcache/tests/jit/gh18136.phpt | 35 ++++++++++++++++++++++ win32/build/config.w32 | 11 ++++++- 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 Zend/asm/save_xmm_x86_64_ms_masm.asm create mode 100644 ext/opcache/tests/jit/gh18136.phpt diff --git a/NEWS b/NEWS index cab0e696f2a6f..720f0bbc6bcc7 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ PHP NEWS - Opcache: . Fixed bug GH-18294 (assertion failure zend_jit_ir.c). (nielsdos) . Fixed bug GH-18289 (Fix segfault in JIT). (Florian Engelhardt) + . Fixed bug GH-18136 (tracing JIT floating point register clobbering on + Windows and ARM64). (nielsdos) - OpenSSL: . Fix memory leak in openssl_sign() when passing invalid algorithm. diff --git a/Zend/asm/save_xmm_x86_64_ms_masm.asm b/Zend/asm/save_xmm_x86_64_ms_masm.asm new file mode 100644 index 0000000000000..1569d6bdb0e86 --- /dev/null +++ b/Zend/asm/save_xmm_x86_64_ms_masm.asm @@ -0,0 +1,43 @@ +.code + +; ZEND_API void execute_ex(zend_execute_data *ex) +PUBLIC execute_ex + +EXTERN execute_ex_real:PROC + +; Assembly wrapper around the real execute_ex function, so that we can +; save the preserved registers when re-entering the VM from JIT code. +; See GH-18136. +execute_ex PROC EXPORT FRAME + ; 10 floating points numbers + ; 32 bytes shadow space + ; 8 bytes to align after the return address + sub rsp, 8*10 + 32 + 8 + .allocstack 8*10 + 32 + 8 + .endprolog + movsd qword ptr [rsp + 32 + 8*0], xmm6 + movsd qword ptr [rsp + 32 + 8*1], xmm7 + movsd qword ptr [rsp + 32 + 8*2], xmm8 + movsd qword ptr [rsp + 32 + 8*3], xmm9 + movsd qword ptr [rsp + 32 + 8*4], xmm10 + movsd qword ptr [rsp + 32 + 8*5], xmm11 + movsd qword ptr [rsp + 32 + 8*6], xmm12 + movsd qword ptr [rsp + 32 + 8*7], xmm13 + movsd qword ptr [rsp + 32 + 8*8], xmm14 + movsd qword ptr [rsp + 32 + 8*9], xmm15 + call execute_ex_real + movsd xmm6, qword ptr [rsp + 32 + 8*0] + movsd xmm7, qword ptr [rsp + 32 + 8*1] + movsd xmm8, qword ptr [rsp + 32 + 8*2] + movsd xmm9, qword ptr [rsp + 32 + 8*3] + movsd xmm10, qword ptr [rsp + 32 + 8*4] + movsd xmm11, qword ptr [rsp + 32 + 8*5] + movsd xmm12, qword ptr [rsp + 32 + 8*6] + movsd xmm13, qword ptr [rsp + 32 + 8*7] + movsd xmm14, qword ptr [rsp + 32 + 8*8] + movsd xmm15, qword ptr [rsp + 32 + 8*9] + add rsp, 8*10 + 32 + 8 + ret +execute_ex ENDP + +END diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5270fc841cd8d..dadc57d13f278 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -55037,10 +55037,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDL # pragma GCC optimize("no-gcse") # pragma GCC optimize("no-ivopts") #endif +#ifdef _WIN64 +/* See save_xmm_x86_64_ms_masm.asm */ +void execute_ex_real(zend_execute_data *ex) +#else ZEND_API void execute_ex(zend_execute_data *ex) +#endif { DCL_OPLINE +#if defined(__GNUC__) && defined(__aarch64__) + __asm__ __volatile__ (""::: "v8","v9","v10","v11","v12","v13","v14","v15"); +#endif + #if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_FP_GLOBAL_REG) struct { #ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 717d4ffd3e8af..5b4799cd67c2a 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -5,10 +5,19 @@ # pragma GCC optimize("no-gcse") # pragma GCC optimize("no-ivopts") #endif +#ifdef _WIN64 +/* See save_xmm_x86_64_ms_masm.asm */ +void {%EXECUTOR_NAME%}_ex_real(zend_execute_data *ex) +#else ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex) +#endif { DCL_OPLINE +#if defined(__GNUC__) && defined(__aarch64__) + __asm__ __volatile__ (""::: "v8","v9","v10","v11","v12","v13","v14","v15"); +#endif + {%HELPER_VARS%} {%INTERNAL_LABELS%} diff --git a/ext/opcache/tests/jit/gh18136.phpt b/ext/opcache/tests/jit/gh18136.phpt new file mode 100644 index 0000000000000..e1993440003e5 --- /dev/null +++ b/ext/opcache/tests/jit/gh18136.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-18136 (tracing JIT floating point register clobbering on Windows and ARM64) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=tracing +opcache.jit_buffer_size=64M +opcache.jit_hot_func=4 +opcache.jit_hot_loop=4 +--FILE-- + +--EXPECT-- +float(-347.3205211468715) diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 043f18b275b9d..7180e841ebc48 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -267,7 +267,11 @@ if (TARGET_ARCH == 'arm64') { DEFINE('FIBER_ASM_FLAGS', '/DBOOST_CONTEXT_EXPORT=EXPORT /nologo /c /Fo'); } -ADD_FLAG('ASM_OBJS', '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj $(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj'); +var all_asm_objs = '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj $(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj'; +if (TARGET_ARCH == 'x64') { + all_asm_objs += ' $(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj'; +} +ADD_FLAG('ASM_OBJS', all_asm_objs); MFO.WriteLine('$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\jump_' + FIBER_ASM_ABI + '.asm'); MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\jump_$(FIBER_ASM_ABI).obj Zend\\asm\\jump_$(FIBER_ASM_ABI).asm'); @@ -275,6 +279,11 @@ MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\jump_$( MFO.WriteLine('$(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\make_' + FIBER_ASM_ABI + '.asm'); MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\make_$(FIBER_ASM_ABI).obj Zend\\asm\\make_$(FIBER_ASM_ABI).asm'); +if (TARGET_ARCH == 'x64') { + MFO.WriteLine('$(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj: Zend\\asm\\save_xmm_x86_64_ms_masm.asm'); + MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj Zend\\asm\\save_xmm_x86_64_ms_masm.asm'); +} + ADD_FLAG("CFLAGS_BD_ZEND", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); if (VS_TOOLSET && VCVERS >= 1914) { ADD_FLAG("CFLAGS_BD_ZEND", "/d2FuncCache1"); From 81d9a27c47b12ad20e180afb09c6188c8d403f9f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:59:12 +0200 Subject: [PATCH 367/503] Fix some leaks in php_scandir Closes GH-18371. --- NEWS | 1 + main/php_scandir.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 55a58a4d8e78f..c24fefcc8c6ed 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - Core: . Fixed bug GH-18304 (Changing the properties of a DateInterval through dynamic properties triggers a SegFault). (nielsdos) + . Fix some leaks in php_scandir. (nielsdos) - Filter: . Fixed bug GH-18309 (ipv6 filter integer overflow). (nielsdos) diff --git a/main/php_scandir.c b/main/php_scandir.c index 7d1eb36023665..7bf91bdf7f33d 100644 --- a/main/php_scandir.c +++ b/main/php_scandir.c @@ -83,7 +83,7 @@ PHPAPI int php_scandir(const char *dirname, struct dirent **namelist[], int (*se newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *)); if (!newv) { - return -1; + goto fail; } vector = newv; } @@ -113,6 +113,7 @@ PHPAPI int php_scandir(const char *dirname, struct dirent **namelist[], int (*se free(vector[nfiles]); } free(vector); + closedir(dirp); return -1; } #endif From 8f6bc97a3601996db3e88a111cd19c2176710ebb Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 13:43:44 +0100 Subject: [PATCH 368/503] ext/pgsql: pg_fetch_all_columns/pg_copy_to arrays optimisations. (#18374) changes to packed arrays for output userland values. --- ext/pgsql/pgsql.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index c53bf8ed9a35c..745b247c66130 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2186,17 +2186,18 @@ PHP_FUNCTION(pg_fetch_all_columns) RETURN_THROWS(); } - array_init(return_value); - if ((pg_numrows = PQntuples(pgsql_result)) <= 0) { - return; + RETURN_EMPTY_ARRAY(); } + array_init_size(return_value, pg_numrows); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for (pg_row = 0; pg_row < pg_numrows; pg_row++) { if (PQgetisnull(pgsql_result, pg_row, (int)colno)) { - add_next_index_null(return_value); + add_index_null(return_value, pg_row); } else { - add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, (int)colno)); + add_index_string(return_value, pg_row, PQgetvalue(pgsql_result, pg_row, (int)colno)); } } } @@ -3363,6 +3364,7 @@ PHP_FUNCTION(pg_copy_to) PQclear(pgsql_result); array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); while (!copydone) { int ret = PQgetCopyData(pgsql, &csv, 0); From 0c2025cdc4c534073906bbdcf1f2df26c66cb1ca Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 13:47:53 +0100 Subject: [PATCH 369/503] ext/tidy: array optimisations, children node arrays as packed. (#18375) --- ext/tidy/tidy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index c5efe7a5b242d..138288dd59d4e 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -705,6 +705,7 @@ static void tidy_add_node_default_properties(PHPTidyObj *obj) if (tempnode) { array_init(&children); + zend_hash_real_init_packed(Z_ARRVAL(children)); do { tidy_create_node_object(&temp, obj->ptdoc, tempnode); add_next_index_zval(&children, &temp); From df39586a882f99c1a3082535c8cb90c562adcce5 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 14:47:52 +0100 Subject: [PATCH 370/503] ext/zlib: gzfile() files list as packed array (#18380) --- ext/zlib/zlib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 0c5486846c12c..f47d879295ced 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -631,6 +631,7 @@ PHP_FUNCTION(gzfile) /* Initialize return array */ array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); /* Now loop through the file and do the magic quotes thing if needed */ memset(buf, 0, sizeof(buf)); From bd8c770439821882df864455b196fc8586d6f576 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 16:37:34 +0100 Subject: [PATCH 371/503] ext/sqlite3: querySingle amd fetchArray methods optimisations. (#18385) pre-allocated size for the former and packed array. --- ext/sqlite3/sqlite3.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 068f437c6984b..1396e693d9955 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -701,9 +701,10 @@ PHP_METHOD(SQLite3, querySingle) if (!entire_row) { sqlite_value_to_zval(stmt, 0, return_value); } else { - int i = 0; - array_init(return_value); - for (i = 0; i < sqlite3_data_count(stmt); i++) { + int i = 0, count = sqlite3_data_count(stmt); + + array_init_size(return_value, count); + for (i = 0; i < count; i++) { zval data; sqlite_value_to_zval(stmt, i, &data); add_assoc_zval(return_value, (char*)sqlite3_column_name(stmt, i), &data); From 4621423e5e3c303fac87f3c16b2679fbc62ebe3d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 21 Apr 2025 15:54:29 +0200 Subject: [PATCH 372/503] Fix uouv in pg_put_copy_end() Closes GH-18383. --- NEWS | 3 +++ ext/pgsql/pgsql.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0790cae953092..efb76ac127a60 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,9 @@ PHP NEWS - PDO Sqlite: . Fix memory leak on error return of collation callback. (nielsdos) +- PgSql: + . Fix uouv in pg_put_copy_end(). (nielsdos) + - SPL: . Fixed bug GH-18322 (SplObjectStorage debug handler mismanages memory). (nielsdos) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index c0d4a5117aefc..75b987d6b917e 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -6215,7 +6215,7 @@ PHP_FUNCTION(pg_put_copy_end) { zval *pgsql_link; pgsql_link_handle *link; - zend_string *error; + zend_string *error = NULL; char *err = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) From 3b387ef27476409992de330827a1a0e42585376c Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 17:03:35 +0100 Subject: [PATCH 373/503] ext/standard: stream_get_filters() user filters list as packed arrays. (#18384) --- ext/standard/user_filters.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 88facf1e137f2..d91e168ce53a7 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -476,16 +476,19 @@ PHP_FUNCTION(stream_get_filters) ZEND_PARSE_PARAMETERS_NONE(); - array_init(return_value); filters_hash = php_get_stream_filters_hash(); if (filters_hash && !HT_IS_PACKED(filters_hash)) { + array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_MAP_FOREACH_STR_KEY(filters_hash, filter_name) { if (filter_name) { add_next_index_str(return_value, zend_string_copy(filter_name)); } } ZEND_HASH_FOREACH_END(); + } else { + RETURN_EMPTY_ARRAY(); } /* It's okay to return an empty array if no filters are registered */ } From b233c55b123ee64f3d59e4bc81b149f79fd0b523 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 17:13:57 +0100 Subject: [PATCH 374/503] ext/curl: curl_getinfo, curl_multi_get_handles and curl_multi_setopt array optimisations. (#18389) mainly change to packed arrays. --- ext/curl/interface.c | 1 + ext/curl/multi.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 8458cd77dabd2..a087da78c37e4 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2747,6 +2747,7 @@ PHP_FUNCTION(curl_getinfo) if (curl_easy_getinfo(ch->cp, option, &slist) == CURLE_OK) { struct curl_slist *current = slist; array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); while (current) { add_next_index_string(return_value, current->data); current = current->next; diff --git a/ext/curl/multi.c b/ext/curl/multi.c index fd0a8316646f6..f664bc05e0e89 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -185,7 +185,8 @@ PHP_FUNCTION(curl_multi_get_handles) mh = Z_CURL_MULTI_P(z_mh); - array_init(return_value); + array_init_size(return_value, zend_llist_count(&mh->easyh)); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); zend_llist_position pos; zval *pz_ch; @@ -420,10 +421,11 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea ch->cp = easy; _php_setup_easy_copy_handlers(ch, parent); - array_init(&headers); + array_init_size(&headers, num_headers); + zend_hash_real_init_packed(Z_ARRVAL(headers)); for (size_t i = 0; i < num_headers; i++) { char *header = curl_pushheader_bynum(push_headers, i); - add_next_index_string(&headers, header); + add_index_string(&headers, i, header); } ZEND_ASSERT(pz_parent_ch); From 32a45769d1f9af69e3583c6e2e9cf8d9b59de867 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 21 Apr 2025 20:49:21 +0100 Subject: [PATCH 375/503] ext/calendar: array optimisations. (#18388) turn arrays to packed when applied/pre-allocate sizes. --- ext/calendar/calendar.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index a0503dab0600f..0f9a4b99a37bc 100644 --- a/ext/calendar/calendar.c +++ b/ext/calendar/calendar.c @@ -131,8 +131,10 @@ static void _php_cal_info(int cal, zval *ret) calendar = &cal_conversion_table[cal]; array_init(ret); - array_init(&months); - array_init(&smonths); + array_init_size(&months, calendar->num_months + 1); + array_init_size(&smonths, calendar->num_months + 1); + zend_hash_real_init_packed(Z_ARRVAL(months)); + zend_hash_real_init_packed(Z_ARRVAL(smonths)); for (i = 1; i <= calendar->num_months; i++) { add_index_string(&months, i, calendar->month_name_long[i]); @@ -160,7 +162,8 @@ PHP_FUNCTION(cal_info) int i; zval val; - array_init(return_value); + array_init_size(return_value, CAL_NUM_CALS); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i = 0; i < CAL_NUM_CALS; i++) { _php_cal_info(i, &val); From 2852177f4d7cdfb0281c38e5431bf903815edfff Mon Sep 17 00:00:00 2001 From: Eric Mann Date: Tue, 22 Apr 2025 06:09:24 -0700 Subject: [PATCH 376/503] PHP-8.3 is now for PHP 8.3.22-dev --- NEWS | 4 +++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index c24fefcc8c6ed..9a227d8dbb085 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.21 +?? ??? ????, PHP 8.3.22 + +08 May 2025, PHP 8.3.21 - Core: . Fixed bug GH-18304 (Changing the properties of a DateInterval through diff --git a/Zend/zend.h b/Zend/zend.h index 139e6a70e15dd..99b88992475bf 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.21-dev" +#define ZEND_VERSION "4.3.22-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index d721458a73eb2..278dbd110d248 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.21-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.22-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index eb91f434188c6..6cec820ba471b 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 -#define PHP_RELEASE_VERSION 21 +#define PHP_RELEASE_VERSION 22 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.21-dev" -#define PHP_VERSION_ID 80321 +#define PHP_VERSION "8.3.22-dev" +#define PHP_VERSION_ID 80322 From 33b977e36b804f58e20021928600e9ef83372014 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Tue, 22 Apr 2025 22:23:08 +0900 Subject: [PATCH 377/503] PHP-8.4 is now for PHP 8.4.8-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index efb76ac127a60..6cf8816e8fc7f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.4.7 +?? ??? ????, PHP 8.4.8 + + +24 Apr 2025, PHP 8.4.7 - Core: . Fixed bug GH-17711 and GH-18022 (Infinite recursion on deprecated attribute diff --git a/Zend/zend.h b/Zend/zend.h index 2e5fb5d0ef091..0ce9956c99c99 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.4.7-dev" +#define ZEND_VERSION "4.4.8-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 0e12d55b00963..6dc1e45b34fd6 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.4.7-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.4.8-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 414e0e8f5a68a..9ac406dfc3208 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 4 -#define PHP_RELEASE_VERSION 7 +#define PHP_RELEASE_VERSION 8 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.4.7-dev" -#define PHP_VERSION_ID 80407 +#define PHP_VERSION "8.4.8-dev" +#define PHP_VERSION_ID 80408 From 27b83e30952bf3a3b2cdf4000218acbdf1cd5f06 Mon Sep 17 00:00:00 2001 From: Eric Mann Date: Tue, 22 Apr 2025 06:26:19 -0700 Subject: [PATCH 378/503] Change RC downloads scp instructions as per the new jump box documentation --- docs/release-process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-process.md b/docs/release-process.md index 36963b4318ead..4c37d2b087390 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -325,7 +325,7 @@ slightly different steps. We'll call attention where the steps differ. downloads.php.net. ```shell - scp php-X.Y.ZRCn.tar.* downloads.php.net:~/public_html/ + scp php-X.Y.ZRCn.tar.* downloads.internal.php.net:~/public_html/ ``` > 💬 **Hint** \ From c9f3127ca8d51767aa7ac0f2100a6396d8365839 Mon Sep 17 00:00:00 2001 From: Carlos Buenosvinos Date: Sun, 13 Apr 2025 14:19:03 +0200 Subject: [PATCH 379/503] Fix GH-18076: date_sun_info() function returns inaccurate sunrise and sunset times Closes GH-18317: Avoid double counting the 15 minutes radial correction of the sun --- ext/date/php_date.c | 2 +- ext/date/tests/bug-gh18076.phpt | 12 ++++++++++++ ext/date/tests/date_sun_info_001.phpt | 4 ++-- ext/date/tests/date_sun_info_002.phpt | 4 ++-- 4 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 ext/date/tests/bug-gh18076.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index c1faa842f8a12..d8a0704ca250a 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5418,7 +5418,7 @@ PHP_FUNCTION(date_sun_info) array_init(return_value); /* Get sun up/down and transit */ - rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -50.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit); + rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit); switch (rs) { case -1: /* always below */ add_assoc_bool(return_value, "sunrise", 0); diff --git a/ext/date/tests/bug-gh18076.phpt b/ext/date/tests/bug-gh18076.phpt new file mode 100644 index 0000000000000..2c1eaa200fad3 --- /dev/null +++ b/ext/date/tests/bug-gh18076.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-18076 (Since PHP 8, date_sun_info() returns inaccurate sunrise and sunset times) +--FILE-- + +--EXPECT-- +05:59:21 +18:14:48 diff --git a/ext/date/tests/date_sun_info_001.phpt b/ext/date/tests/date_sun_info_001.phpt index 708d2550ccac5..c9096af46d4b1 100644 --- a/ext/date/tests/date_sun_info_001.phpt +++ b/ext/date/tests/date_sun_info_001.phpt @@ -10,9 +10,9 @@ echo "Done\n"; --EXPECT-- array(9) { ["sunrise"]=> - int(1165897682) + int(1165897761) ["sunset"]=> - int(1165934239) + int(1165934160) ["transit"]=> int(1165915961) ["civil_twilight_begin"]=> diff --git a/ext/date/tests/date_sun_info_002.phpt b/ext/date/tests/date_sun_info_002.phpt index 1ff58295e31e3..ac319796d61c9 100644 --- a/ext/date/tests/date_sun_info_002.phpt +++ b/ext/date/tests/date_sun_info_002.phpt @@ -11,8 +11,8 @@ foreach ($sun_info as $key => $elem ) echo "Done\n"; ?> --EXPECT-- -2007-04-13 06:11:26 CEST sunrise -2007-04-13 20:32:56 CEST sunset +2007-04-13 06:13:31 CEST sunrise +2007-04-13 20:30:51 CEST sunset 2007-04-13 13:22:11 CEST transit 2007-04-13 05:29:22 CEST civil_twilight_begin 2007-04-13 21:15:00 CEST civil_twilight_end From c97bdce962d609f435fea26c97324e7b5ff2f4f4 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 17 Apr 2025 13:52:17 +0200 Subject: [PATCH 380/503] Evaluate const expression cast at ct if possible Related to GH-18264 Closes GH-18347 --- Zend/Optimizer/zend_optimizer.c | 27 +------- .../constexpr/constant_expressions_cast.phpt | 65 +++++++++++++++++++ Zend/zend_compile.c | 32 +++++++++ Zend/zend_compile.h | 2 + 4 files changed, 101 insertions(+), 25 deletions(-) diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 9f2e3115d3666..fd8735354c6da 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -82,31 +82,8 @@ zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1 zend_result zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1) /* {{{ */ { - switch (type) { - case IS_NULL: - ZVAL_NULL(result); - return SUCCESS; - case _IS_BOOL: - ZVAL_BOOL(result, zval_is_true(op1)); - return SUCCESS; - case IS_LONG: - ZVAL_LONG(result, zval_get_long(op1)); - return SUCCESS; - case IS_DOUBLE: - ZVAL_DOUBLE(result, zval_get_double(op1)); - return SUCCESS; - case IS_STRING: - /* Conversion from double to string takes into account run-time - 'precision' setting and cannot be evaluated at compile-time */ - if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) { - ZVAL_STR(result, zval_get_string(op1)); - return SUCCESS; - } - break; - case IS_ARRAY: - ZVAL_COPY(result, op1); - convert_to_array(result); - return SUCCESS; + if (zend_try_ct_eval_cast(result, type, op1)) { + return SUCCESS; } return FAILURE; } diff --git a/Zend/tests/constexpr/constant_expressions_cast.phpt b/Zend/tests/constexpr/constant_expressions_cast.phpt index 4431e2c08d6b0..0fd7c48260c18 100644 --- a/Zend/tests/constexpr/constant_expressions_cast.phpt +++ b/Zend/tests/constexpr/constant_expressions_cast.phpt @@ -18,6 +18,28 @@ const T9 = (array) new DateTime; const T10 = (int) new DateTime; var_dump(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); + +const C_FLOAT = 0.3; +const C_EMPTY_ARRAY = []; +const C_ARRAY = ["a" => 1]; +const C_INT = 5; +const C_EMPTY_STRING = ""; +const C_CALLABLE = var_dump(...); +const C_USER_OBJECT = new X; +const C_DATE_TIME = new DateTime; + +const T11 = (int) C_FLOAT; +const T12 = (bool) C_FLOAT; +const T13 = (string) C_EMPTY_ARRAY; +const T14 = (object) C_ARRAY; +const T15 = (float) C_INT; +const T16 = (array) C_EMPTY_STRING; +const T17 = (array) C_CALLABLE; +const T18 = (array) C_USER_OBJECT; +const T19 = (array) C_DATE_TIME; +const T20 = (int) C_DATE_TIME; + +var_dump(T11, T12, T13, T14, T15, T16, T17, T18, T19, T20); ?> --EXPECTF-- Warning: Array to string conversion in %s on line %d @@ -62,3 +84,46 @@ array(3) { string(%d) "%s" } int(1) + +Warning: Array to string conversion in %s on line %d + +Warning: Object of class DateTime could not be converted to int in %s on line %d +int(0) +bool(true) +string(5) "Array" +object(stdClass)#%d (1) { + ["a"]=> + int(1) +} +float(5) +array(1) { + [0]=> + string(0) "" +} +array(1) { + [0]=> + object(Closure)#%d (2) { + ["function"]=> + string(8) "var_dump" + ["parameter"]=> + array(2) { + ["$value"]=> + string(10) "" + ["$values"]=> + string(10) "" + } + } +} +array(1) { + ["foo"]=> + int(3) +} +array(3) { + ["date"]=> + string(%d) "%s" + ["timezone_type"]=> + int(%d) + ["timezone"]=> + string(%d) "%s" +} +int(1) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5c15832f80a89..d05e2d21ed748 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -11842,6 +11842,34 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t } /* }}} */ +bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1) +{ + switch (type) { + case _IS_BOOL: + ZVAL_BOOL(result, zval_is_true(op1)); + return true; + case IS_LONG: + ZVAL_LONG(result, zval_get_long(op1)); + return true; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(op1)); + return true; + case IS_STRING: + /* Conversion from double to string takes into account run-time + 'precision' setting and cannot be evaluated at compile-time */ + if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) { + ZVAL_STR(result, zval_get_string(op1)); + return true; + } + break; + case IS_ARRAY: + ZVAL_COPY(result, op1); + convert_to_array(result); + return true; + } + return false; +} + static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ { zend_ast *ast = *ast_ptr; @@ -12129,6 +12157,10 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ return; case ZEND_AST_CAST: zend_eval_const_expr(&ast->child[0]); + if (ast->child[0]->kind == ZEND_AST_ZVAL + && zend_try_ct_eval_cast(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) { + break; + } return; default: return; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 4f7d158ba0f1c..aec72743f6ca9 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1301,4 +1301,6 @@ ZEND_API bool zend_is_op_long_compatible(const zval *op); ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, const zval *op2); ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op); +bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1); + #endif /* ZEND_COMPILE_H */ From 03d2226f45460e9e059bd18097567aa12c11a755 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 10 Apr 2025 16:36:32 +0200 Subject: [PATCH 381/503] Fix self inheritance type checks for traits Fixes GH-18295 Closes GH-18296 --- Zend/tests/inheritance/bug70957.phpt | 2 +- Zend/tests/traits/bug78776.phpt | 2 +- Zend/tests/traits/bug81192.phpt | 2 +- .../tests/traits/bugs/abstract-methods05.phpt | 2 +- .../tests/traits/bugs/abstract-methods06.phpt | 2 +- Zend/tests/traits/gh18295.phpt | 21 +++++++++++++++++++ Zend/tests/traits/inheritance003.phpt | 2 +- .../variance/trait_error.phpt | 2 +- Zend/zend_inheritance.c | 17 ++++++++++----- 9 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 Zend/tests/traits/gh18295.phpt diff --git a/Zend/tests/inheritance/bug70957.phpt b/Zend/tests/inheritance/bug70957.phpt index 9341fcd288d95..6e5a51d9edea4 100644 --- a/Zend/tests/inheritance/bug70957.phpt +++ b/Zend/tests/inheritance/bug70957.phpt @@ -19,4 +19,4 @@ class B extends Foo } ?> --EXPECTF-- -Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = 'Foo') in %s on line %d +Fatal error: Declaration of B::bar() must be compatible with Foo::bar($a = 'Foo') in %s on line %d diff --git a/Zend/tests/traits/bug78776.phpt b/Zend/tests/traits/bug78776.phpt index 3696d955a3a3e..feecfeb8fddd4 100644 --- a/Zend/tests/traits/bug78776.phpt +++ b/Zend/tests/traits/bug78776.phpt @@ -25,4 +25,4 @@ B::createApp(); ?> --EXPECTF-- -Fatal error: Cannot make non static method A::createApp() static in class C in %s on line %d +Fatal error: Cannot make non static method A::createApp() static in class B in %s on line %d diff --git a/Zend/tests/traits/bug81192.phpt b/Zend/tests/traits/bug81192.phpt index 00f6f1d2fbf71..268df826ddfde 100644 --- a/Zend/tests/traits/bug81192.phpt +++ b/Zend/tests/traits/bug81192.phpt @@ -17,4 +17,4 @@ class B extends A { ?> --EXPECTF-- -Fatal error: Declaration of T::foo(): string must be compatible with A::foo(): int in %sbug81192_trait.inc on line 4 +Fatal error: Declaration of B::foo(): string must be compatible with A::foo(): int in %sbug81192_trait.inc on line 4 diff --git a/Zend/tests/traits/bugs/abstract-methods05.phpt b/Zend/tests/traits/bugs/abstract-methods05.phpt index 96619eae910b8..e0ffc60c14921 100644 --- a/Zend/tests/traits/bugs/abstract-methods05.phpt +++ b/Zend/tests/traits/bugs/abstract-methods05.phpt @@ -22,4 +22,4 @@ class TraitsTest1 { ?> --EXPECTF-- -Fatal error: Declaration of THelloB::hello() must be compatible with THelloA::hello($a) in %s on line %d +Fatal error: Declaration of TraitsTest1::hello() must be compatible with THelloA::hello($a) in %s on line %d diff --git a/Zend/tests/traits/bugs/abstract-methods06.phpt b/Zend/tests/traits/bugs/abstract-methods06.phpt index 8e2f25b048e0b..82ad805aed538 100644 --- a/Zend/tests/traits/bugs/abstract-methods06.phpt +++ b/Zend/tests/traits/bugs/abstract-methods06.phpt @@ -23,4 +23,4 @@ class TraitsTest1 { ?> --EXPECTF-- -Fatal error: Declaration of THelloB::hello() must be compatible with THelloA::hello($a) in %s on line %d +Fatal error: Declaration of TraitsTest1::hello() must be compatible with THelloA::hello($a) in %s on line %d diff --git a/Zend/tests/traits/gh18295.phpt b/Zend/tests/traits/gh18295.phpt new file mode 100644 index 0000000000000..438431a5b4eec --- /dev/null +++ b/Zend/tests/traits/gh18295.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-18295: Parent self is substitutable with child self through trait +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/traits/inheritance003.phpt b/Zend/tests/traits/inheritance003.phpt index 1e630eef61d88..1826a084c5a01 100644 --- a/Zend/tests/traits/inheritance003.phpt +++ b/Zend/tests/traits/inheritance003.phpt @@ -35,4 +35,4 @@ $o->sayHello(array()); --EXPECTF-- World! -Fatal error: Declaration of SayWorld::sayHello(Base $d) must be compatible with Base::sayHello(array $a) in %s on line %d +Fatal error: Declaration of MyHelloWorld::sayHello(Base $d) must be compatible with Base::sayHello(array $a) in %s on line %d diff --git a/Zend/tests/type_declarations/variance/trait_error.phpt b/Zend/tests/type_declarations/variance/trait_error.phpt index 667b177a5b931..dd4ac59d8e7e8 100644 --- a/Zend/tests/type_declarations/variance/trait_error.phpt +++ b/Zend/tests/type_declarations/variance/trait_error.phpt @@ -17,4 +17,4 @@ class U extends X { ?> --EXPECTF-- -Fatal error: Could not check compatibility between T::method($r): B and X::method($a): A, because class B is not available in %s on line %d +Fatal error: Could not check compatibility between U::method($r): B and X::method($a): A, because class B is not available in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 090b1049418d2..e718eb5684e65 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3608,6 +3608,11 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string zend_do_traits_method_binding(ce, traits_and_interfaces, trait_exclude_tables, trait_aliases, false, &trait_contains_abstract_methods); zend_do_traits_constant_binding(ce, traits_and_interfaces); zend_do_traits_property_binding(ce, traits_and_interfaces); + + zend_function *fn; + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { + zend_fixup_trait_method(fn, ce); + } ZEND_HASH_FOREACH_END(); } if (parent) { if (!(parent->ce_flags & ZEND_ACC_LINKED)) { @@ -3618,6 +3623,13 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string if (ce->num_traits) { if (trait_contains_abstract_methods) { zend_do_traits_method_binding(ce, traits_and_interfaces, trait_exclude_tables, trait_aliases, true, &trait_contains_abstract_methods); + + /* New abstract methods may have been added, make sure to add + * ZEND_ACC_IMPLICIT_ABSTRACT_CLASS to ce. */ + zend_function *fn; + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { + zend_fixup_trait_method(fn, ce); + } ZEND_HASH_FOREACH_END(); } if (trait_exclude_tables) { @@ -3634,11 +3646,6 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string if (trait_aliases) { efree(trait_aliases); } - - zend_function *fn; - ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { - zend_fixup_trait_method(fn, ce); - } ZEND_HASH_FOREACH_END(); } if (ce->num_interfaces) { /* Also copy the parent interfaces here, so we don't need to reallocate later. */ From 1b4bca605cc6a0b3ddda9b5230120bdec769ac89 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 21 Apr 2025 14:51:46 +0200 Subject: [PATCH 382/503] Add assertion as optimization hint in php_url_encode_impl() This avoids the code bloat induced by zend_string_truncate(). --- ext/standard/url.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/standard/url.c b/ext/standard/url.c index 7d564b510bc9f..817f73158637f 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -536,6 +536,7 @@ static zend_always_inline zend_string *php_url_encode_impl(const char *s, size_t } *to = '\0'; + ZEND_ASSERT(!ZSTR_IS_INTERNED(start) && GC_REFCOUNT(start) == 1); start = zend_string_truncate(start, to - (unsigned char*)ZSTR_VAL(start), 0); return start; From 68794e074b2f7fe2fab5af183ff8d88cefe9b51d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 21 Apr 2025 14:52:25 +0200 Subject: [PATCH 383/503] Use RETURN_NEW_STR() in url.c This avoids an extra branch. --- ext/standard/url.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/url.c b/ext/standard/url.c index 817f73158637f..3d704b0140ca9 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -559,7 +559,7 @@ PHP_FUNCTION(urlencode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - RETURN_STR(php_url_encode(ZSTR_VAL(in_str), ZSTR_LEN(in_str))); + RETURN_NEW_STR(php_url_encode(ZSTR_VAL(in_str), ZSTR_LEN(in_str))); } /* }}} */ @@ -621,7 +621,7 @@ PHP_FUNCTION(rawurlencode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - RETURN_STR(php_raw_url_encode(ZSTR_VAL(in_str), ZSTR_LEN(in_str))); + RETURN_NEW_STR(php_raw_url_encode(ZSTR_VAL(in_str), ZSTR_LEN(in_str))); } /* }}} */ From 54a0a7924ae217570b358d24733a2e979ce86dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 22 Apr 2025 20:18:08 +0200 Subject: [PATCH 384/503] fileinfo: Change return type of `finfo_close()` to `true` (#18395) This function is a noop and always returns `true`. --- NEWS | 1 + UPGRADING | 3 +++ ext/fileinfo/fileinfo.stub.php | 2 +- ext/fileinfo/fileinfo_arginfo.h | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 47bf820d6b64c..bef0ac90460a0 100644 --- a/NEWS +++ b/NEWS @@ -69,6 +69,7 @@ PHP NEWS - Fileinfo: . Upgrade to file 5.46. (nielsdos) + . Change return type of finfo_close() to true. (timwolla) - FPM: . Fixed GH-17645 (FPM with httpd ProxyPass does not decode script path). diff --git a/UPGRADING b/UPGRADING index 6b6c555adcf73..36be5313ab6c5 100644 --- a/UPGRADING +++ b/UPGRADING @@ -348,6 +348,9 @@ PHP 8.5 UPGRADE NOTES - Fileinfo: . Upgraded to file 5.46. + . The return type of finfo_close() has been changed to true, rather + than bool. + - PCRE: . Upgraded to pcre2lib from 10.44 to 10.45. diff --git a/ext/fileinfo/fileinfo.stub.php b/ext/fileinfo/fileinfo.stub.php index 6fc2cc4c7b4e5..2dba0fe2659ef 100644 --- a/ext/fileinfo/fileinfo.stub.php +++ b/ext/fileinfo/fileinfo.stub.php @@ -92,7 +92,7 @@ public function set_flags(int $flags): true {} /** @refcount 1 */ function finfo_open(int $flags = FILEINFO_NONE, ?string $magic_database = null): finfo|false {} -function finfo_close(finfo $finfo): bool {} +function finfo_close(finfo $finfo): true {} function finfo_set_flags(finfo $finfo, int $flags): true {} diff --git a/ext/fileinfo/fileinfo_arginfo.h b/ext/fileinfo/fileinfo_arginfo.h index 36b9351ea1387..024e7d4b6bd59 100644 --- a/ext/fileinfo/fileinfo_arginfo.h +++ b/ext/fileinfo/fileinfo_arginfo.h @@ -1,12 +1,12 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 96d78126bc5af37c5d94fa160e509623e947de48 */ + * Stub hash: d5bc322159e4af87077c07ddaca0a77803b4743a */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_finfo_open, 0, 0, finfo, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "FILEINFO_NONE") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, magic_database, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_finfo_close, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_finfo_close, 0, 1, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, finfo, finfo, 0) ZEND_END_ARG_INFO() From b6bbd80212cc430f83b2e9efd59171544891c5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 22 Apr 2025 20:33:03 +0200 Subject: [PATCH 385/503] [skip ci] Formatting in UPGRADING --- UPGRADING | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UPGRADING b/UPGRADING index 36be5313ab6c5..1b2779c8c1e7c 100644 --- a/UPGRADING +++ b/UPGRADING @@ -97,7 +97,7 @@ PHP 8.5 UPGRADE NOTES long on a PDOStatement resulting from the Firebird driver. - SimpleXML: - - Passing an XPath expression that returns something other than a node set + . Passing an XPath expression that returns something other than a node set to SimpleXMLElement::xpath() will now emit a warning and return false, instead of silently failing and returning an empty array. @@ -197,9 +197,9 @@ PHP 8.5 UPGRADE NOTES ======================================== - Hash: - The MHASH_* constants have been deprecated. These have been overlooked - when the mhash*() function family has been deprecated per - https://wiki.php.net/rfc/deprecations_php_8_1#mhash_function_family + . The MHASH_* constants have been deprecated. These have been overlooked + when the mhash*() function family has been deprecated per + https://wiki.php.net/rfc/deprecations_php_8_1#mhash_function_family ======================================== 5. Changed Functions From 92cec8add5746b6de6b00a01fc491e333c6aaf13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 22 Apr 2025 22:24:49 +0200 Subject: [PATCH 386/503] fileinfo: Fix cleanup in ext/fileinfo/tests/cve-2014-1943-mb.phpt (#18397) This also removes an accidentally committed file. --- ext/fileinfo/tests/cve-2014-1943-mb.phpt | 4 +- ...\343\202\214\343\201\276\343\201\231.data" | 1 - ...343\202\214\343\201\276\343\201\231.magic" | 2 - ...\343\202\214\343\201\276\343\201\231.data" | 1000000 -------------- 4 files changed, 2 insertions(+), 1000005 deletions(-) delete mode 100644 "ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" delete mode 100644 "ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.magic" delete mode 100644 "ext/fileinfo/tests/cve-2014-3538\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" diff --git a/ext/fileinfo/tests/cve-2014-1943-mb.phpt b/ext/fileinfo/tests/cve-2014-1943-mb.phpt index f15f7dba3d3a0..576f3ac370039 100644 --- a/ext/fileinfo/tests/cve-2014-1943-mb.phpt +++ b/ext/fileinfo/tests/cve-2014-1943-mb.phpt @@ -26,8 +26,8 @@ finfo_close($fi); Done --CLEAN-- --EXPECTF-- string(%d) "%s" diff --git "a/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" "b/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" deleted file mode 100644 index c4416f4eb4f69..0000000000000 --- "a/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git "a/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.magic" "b/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.magic" deleted file mode 100644 index 75a8a70f978de..0000000000000 --- "a/ext/fileinfo/tests/cve-2014-1943\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.magic" +++ /dev/null @@ -1,2 +0,0 @@ -0 byte x ->(1.b) indirect x diff --git "a/ext/fileinfo/tests/cve-2014-3538\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" "b/ext/fileinfo/tests/cve-2014-3538\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" deleted file mode 100644 index c5a77dc0136f2..0000000000000 --- "a/ext/fileinfo/tests/cve-2014-3538\347\247\201\343\201\257\343\202\254\343\203\251\343\202\271\343\202\222\351\243\237\343\201\271\343\202\211\343\202\214\343\201\276\343\201\231.data" +++ /dev/null @@ -1,1000000 +0,0 @@ -try: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 518945050021ae0802d4b7d8de1486a7f4fea913 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 22 Apr 2025 23:39:05 +0100 Subject: [PATCH 387/503] ext/intl: Locale::* methods using param as path whenever relevant. (#18365) close GH-18365 --- NEWS | 1 + UPGRADING | 2 ++ ext/intl/locale/locale_methods.c | 28 ++++++++++-------- .../tests/locale_filter_matches_icu70.phpt | 16 ++++++++++ ext/intl/tests/locale_get_all_variants.phpt | 8 +++++ .../tests/locale_get_display_language4.phpt | 29 +++++++++++++++++++ .../tests/locale_get_display_script4.phpt | 16 ++++++++++ ext/intl/tests/locale_get_region.phpt | 8 +++++ ext/intl/tests/locale_get_script.phpt | 8 +++++ ext/intl/tests/locale_is_right_to_left.phpt | 6 ++++ ext/intl/tests/locale_lookup_variant3.phpt | 24 +++++++++++++++ ext/intl/tests/locale_set_default.phpt | 8 +++++ 12 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 ext/intl/tests/locale_get_display_language4.phpt diff --git a/NEWS b/NEWS index bef0ac90460a0..a3d278ac2e3b3 100644 --- a/NEWS +++ b/NEWS @@ -88,6 +88,7 @@ PHP NEWS (BogdanUngureanu) . Added Locale::isRightToLeft to check if a locale is written right to left. (David Carlier) + . Added null bytes presence in locale inputs for Locale class. (David Carlier) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 1b2779c8c1e7c..40645a28ac600 100644 --- a/UPGRADING +++ b/UPGRADING @@ -212,6 +212,8 @@ PHP 8.5 UPGRADE NOTES . grapheme_extract() properly assigns $next value when skipping over invalid starting bytes. Previously there were cases where it would point to the start of the grapheme boundary instead of the end. + . Locale:: methods throw a ValueError when locale inputs contain null + bytes. - PCNTL: . pcntl_exec() now has a formal return type of false. diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index bba52a90994cc..684f84c7e323a 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -315,7 +315,7 @@ PHP_NAMED_FUNCTION(zif_locale_set_default) char *default_locale = NULL; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STR(locale_name) + Z_PARAM_PATH_STR(locale_name) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(locale_name) == 0) { @@ -481,7 +481,7 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len == 0) { @@ -568,9 +568,9 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(disp_loc_name, disp_loc_name_len) + Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len > ULOC_FULLNAME_CAPACITY) { @@ -735,7 +735,7 @@ PHP_FUNCTION( locale_get_keywords ) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); INTL_CHECK_LOCALE_LEN(strlen(loc_name)); @@ -1126,7 +1126,7 @@ PHP_FUNCTION(locale_parse) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); INTL_CHECK_LOCALE_LEN(strlen(loc_name)); @@ -1166,7 +1166,7 @@ PHP_FUNCTION(locale_get_all_variants) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len == 0) { @@ -1260,8 +1260,8 @@ PHP_FUNCTION(locale_filter_matches) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(lang_tag, lang_tag_len) - Z_PARAM_STRING(loc_range, loc_range_len) + Z_PARAM_PATH(lang_tag, lang_tag_len) + Z_PARAM_PATH(loc_range, loc_range_len) Z_PARAM_OPTIONAL Z_PARAM_BOOL(boolCanonical) ZEND_PARSE_PARAMETERS_END(); @@ -1434,6 +1434,10 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, zend_argument_type_error(2, "must only contain string values"); LOOKUP_CLEAN_RETURN(NULL); } + if (zend_str_has_nul_byte(Z_STR_P(ele_value))) { + zend_argument_value_error(2, "must not contain any null bytes"); + LOOKUP_CLEAN_RETURN(NULL); + } cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value)); result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[cur_arr_len*2]); if(result == 0) { @@ -1535,10 +1539,10 @@ PHP_FUNCTION(locale_lookup) ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_ARRAY(arr) - Z_PARAM_STRING(loc_range, loc_range_len) + Z_PARAM_PATH(loc_range, loc_range_len) Z_PARAM_OPTIONAL Z_PARAM_BOOL(boolCanonical) - Z_PARAM_STR_OR_NULL(fallback_loc_str) + Z_PARAM_PATH_STR_OR_NULL(fallback_loc_str) ZEND_PARSE_PARAMETERS_END(); if(loc_range_len == 0) { @@ -1626,7 +1630,7 @@ PHP_FUNCTION(locale_is_right_to_left) size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(locale, locale_len) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if (!locale_len) { diff --git a/ext/intl/tests/locale_filter_matches_icu70.phpt b/ext/intl/tests/locale_filter_matches_icu70.phpt index ce30b0565472f..0e0b16af17606 100644 --- a/ext/intl/tests/locale_filter_matches_icu70.phpt +++ b/ext/intl/tests/locale_filter_matches_icu70.phpt @@ -69,6 +69,18 @@ function ut_main() } } + try { + ut_loc_locale_filter_matches("de\0-DE", "de-DE", false); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_filter_matches("de-DE", "d\0e-DE", false); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -79,6 +91,10 @@ ut_run(); ?> --EXPECT-- +Locale::filterMatches(): Argument #1 ($languageTag) must not contain any null bytes +Locale::filterMatches(): Argument #2 ($locale) must not contain any null bytes +locale_filter_matches(): Argument #1 ($languageTag) must not contain any null bytes +locale_filter_matches(): Argument #2 ($locale) must not contain any null bytes -------------- loc_range:de-de matches lang_tag de-DEVA ? NO loc_range:de_DE canonically matches lang_tag de_Deva ? NO diff --git a/ext/intl/tests/locale_get_all_variants.phpt b/ext/intl/tests/locale_get_all_variants.phpt index 5b876d87eda95..12bf82cacac09 100644 --- a/ext/intl/tests/locale_get_all_variants.phpt +++ b/ext/intl/tests/locale_get_all_variants.phpt @@ -39,6 +39,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_locale_get_all_variants("i-\0tay"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -49,6 +55,8 @@ ut_run(); ?> --EXPECT-- +Locale::getAllVariants(): Argument #1 ($locale) must not contain any null bytes +locale_get_all_variants(): Argument #1 ($locale) must not contain any null bytes sl_IT_nedis_KIRTI : variants 'NEDIS','KIRTI', sl_IT_nedis-a-kirti-x-xyz : variants 'NEDIS', sl_IT_rozaj : variants 'ROZAJ', diff --git a/ext/intl/tests/locale_get_display_language4.phpt b/ext/intl/tests/locale_get_display_language4.phpt new file mode 100644 index 0000000000000..1273c4a99968d --- /dev/null +++ b/ext/intl/tests/locale_get_display_language4.phpt @@ -0,0 +1,29 @@ +--TEST-- +locale_get_display_language() throwing null bytes exceptions. +--EXTENSIONS-- +intl +--FILE-- +getMessage(). PHP_EOL; + } + + try { + ut_loc_get_display_language("a-DE", "locale=a\0-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } +} +include_once 'ut_common.inc'; +ut_run(); +?> +--EXPECT-- +Locale::getDisplayLanguage(): Argument #1 ($locale) must not contain any null bytes +Locale::getDisplayLanguage(): Argument #2 ($displayLocale) must not contain any null bytes +locale_get_display_language(): Argument #1 ($locale) must not contain any null bytes +locale_get_display_language(): Argument #2 ($displayLocale) must not contain any null bytes diff --git a/ext/intl/tests/locale_get_display_script4.phpt b/ext/intl/tests/locale_get_display_script4.phpt index 77c630393c88a..5330529330269 100644 --- a/ext/intl/tests/locale_get_display_script4.phpt +++ b/ext/intl/tests/locale_get_display_script4.phpt @@ -83,6 +83,18 @@ function ut_main() $res_str .= "-----------------\n"; } + try { + ut_loc_get_display_script("a-D\0E", "locale=a-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_get_display_script("a-DE", "locale=a\0-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -92,6 +104,10 @@ ut_run(); ?> --EXPECT-- +Locale::getDisplayScript(): Argument #1 ($locale) must not contain any null bytes +Locale::getDisplayScript(): Argument #2 ($displayLocale) must not contain any null bytes +locale_get_display_script(): Argument #1 ($locale) must not contain any null bytes +locale_get_display_script(): Argument #2 ($displayLocale) must not contain any null bytes locale='uk-ua_CALIFORNIA@currency=;currency=GRN' disp_locale=en : display_script= disp_locale=fr : display_script= diff --git a/ext/intl/tests/locale_get_region.phpt b/ext/intl/tests/locale_get_region.phpt index f843397bdb6cf..0c3c1655deb3a 100644 --- a/ext/intl/tests/locale_get_region.phpt +++ b/ext/intl/tests/locale_get_region.phpt @@ -76,6 +76,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_get_region("a-\0DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -85,6 +91,8 @@ ut_run(); ?> --EXPECTF-- +Locale::getRegion(): Argument #1 ($locale) must not contain any null bytes +locale_get_region(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: region='UA' root: region='' uk@currency=EURO: region='' diff --git a/ext/intl/tests/locale_get_script.phpt b/ext/intl/tests/locale_get_script.phpt index e00c83626d5bf..52e0a4155a971 100644 --- a/ext/intl/tests/locale_get_script.phpt +++ b/ext/intl/tests/locale_get_script.phpt @@ -74,6 +74,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_get_script("de\0-419-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -83,6 +89,8 @@ ut_run(); ?> --EXPECT-- +Locale::getScript(): Argument #1 ($locale) must not contain any null bytes +locale_get_script(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: script='' root: script='' uk@currency=EURO: script='' diff --git a/ext/intl/tests/locale_is_right_to_left.phpt b/ext/intl/tests/locale_is_right_to_left.phpt index c586582d42225..c9e4323ff7442 100644 --- a/ext/intl/tests/locale_is_right_to_left.phpt +++ b/ext/intl/tests/locale_is_right_to_left.phpt @@ -8,9 +8,15 @@ var_dump(Locale::isRightToLeft("en-US")); var_dump(Locale::isRightToLeft("\INVALID\\")); var_dump(Locale::isRightToLeft("")); var_dump(Locale::isRightToLeft("ar")); +try { + Locale::isRightToLeft("a\0r"); +} catch (\ValueError $e) { + echo $e->getMessage(); +} ?> --EXPECT-- bool(false) bool(false) bool(false) bool(true) +Locale::isRightToLeft(): Argument #1 ($locale) must not contain any null bytes diff --git a/ext/intl/tests/locale_lookup_variant3.phpt b/ext/intl/tests/locale_lookup_variant3.phpt index c1741a0ed9dd4..b13a54139f443 100644 --- a/ext/intl/tests/locale_lookup_variant3.phpt +++ b/ext/intl/tests/locale_lookup_variant3.phpt @@ -59,6 +59,24 @@ function ut_main() } + try { + ut_loc_locale_lookup(["de\0-DE"], "de-DE", false, "en-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_lookup(["de-DE"], "de-D\0E", true, "en-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_lookup(["de-DE"], "de-DE", true, "e\0n-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -69,6 +87,12 @@ ut_run(); ?> --EXPECT-- +Locale::lookup(): Argument #2 ($locale) must not contain any null bytes +Locale::lookup(): Argument #2 ($locale) must not contain any null bytes +Locale::lookup(): Argument #4 ($defaultLocale) must not contain any null bytes +locale_lookup(): Argument #2 ($locale) must not contain any null bytes +locale_lookup(): Argument #2 ($locale) must not contain any null bytes +locale_lookup(): Argument #4 ($defaultLocale) must not contain any null bytes -------------- loc_range:de-de lang_tags: de-DEVA,de-DE-1996,de-DE,zh_Hans,de-CH-1996,sl_IT,sl_IT_nedis-a-kirti-x-xyz,sl_IT_rozaj,sl_IT_NEDIS_ROJAZ_1901,i-enochian,sgn-CH-de,art-lojban,i-lux,art-lojban,jbo,en_sl_IT,zh-Hant-CN-x-prv1-prv2 diff --git a/ext/intl/tests/locale_set_default.phpt b/ext/intl/tests/locale_set_default.phpt index 0f690aabc2965..6108f370274bb 100644 --- a/ext/intl/tests/locale_set_default.phpt +++ b/ext/intl/tests/locale_set_default.phpt @@ -86,6 +86,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_set_default("a-\0DE"); + } catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; + } + return $res_str; } @@ -95,6 +101,8 @@ ut_run(); ?> --EXPECT-- +Locale::setDefault(): Argument #1 ($locale) must not contain any null bytes +locale_set_default(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: set locale 'uk-ua_CALIFORNIA@currency=;currency=GRN' root: set locale 'root' uk@currency=EURO: set locale 'uk@currency=EURO' From c668ed422593b2037c90f2299e9378542c46078c Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Wed, 23 Apr 2025 09:31:10 +0900 Subject: [PATCH 388/503] [skip ci] NEWS for #18317 --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 9a227d8dbb085..bf57077f4544c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.22 +- Date: + . Fixed bug GH-18076 (Since PHP 8, the date_sun_info() function returns + inaccurate sunrise and sunset times, but other calculated times are + correct) (JiriJozif). + 08 May 2025, PHP 8.3.21 - Core: From 35936bfa79e8972495190cc3cbf0dc60a53fdcea Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 22 Apr 2025 16:10:34 +0200 Subject: [PATCH 389/503] Drop tidyp from FreeBSD build It looks like it's no longer supported. We don't test tidy on FreeBSD anyway. --- .github/actions/freebsd/action.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/actions/freebsd/action.yml b/.github/actions/freebsd/action.yml index ce9ba24451582..1f7c670f27227 100644 --- a/.github/actions/freebsd/action.yml +++ b/.github/actions/freebsd/action.yml @@ -27,7 +27,6 @@ runs: bzip2 \ t1lib \ gmp \ - tidyp \ libsodium \ libzip \ libxml2 \ From 3fdd3ed9f722d9f0aa3122b2340a611db2dfa110 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 22 Apr 2025 19:58:10 +0100 Subject: [PATCH 390/503] backporting C++17 detection support for recent icu4c releases. --- ext/intl/config.m4 | 11 ++++++++- ext/intl/tests/bug62070_3.phpt | 1 + .../tests/collator_get_sort_key_variant7.phpt | 1 + ext/intl/tests/locale_get_display_name8.phpt | 24 +++++++++---------- .../tests/locale_get_display_variant2.phpt | 18 +++++++------- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index daadd3e73d8db..27cd8b3015596 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -85,7 +85,16 @@ if test "$PHP_INTL" != "no"; then breakiterator/codepointiterator_methods.cpp" PHP_REQUIRE_CXX() - PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX) + + AC_MSG_CHECKING([if intl requires -std=gnu++17]) + AS_IF([$PKG_CONFIG icu-uc --atleast-version=74],[ + AC_MSG_RESULT([yes]) + PHP_CXX_COMPILE_STDCXX(17, mandatory, PHP_INTL_STDCXX) + ],[ + AC_MSG_RESULT([no]) + PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX) + ]) + PHP_INTL_CXX_FLAGS="$INTL_COMMON_FLAGS $PHP_INTL_STDCXX $ICU_CXXFLAGS" case $host_alias in *cygwin*) PHP_INTL_CXX_FLAGS="$PHP_INTL_CXX_FLAGS -D_POSIX_C_SOURCE=200809L" diff --git a/ext/intl/tests/bug62070_3.phpt b/ext/intl/tests/bug62070_3.phpt index 08c1bbf45f8ba..60e0593acfd3d 100644 --- a/ext/intl/tests/bug62070_3.phpt +++ b/ext/intl/tests/bug62070_3.phpt @@ -4,6 +4,7 @@ Bug #62070: Collator::getSortKey() returns garbage intl --SKIPIF-- = 62.1'); ?> += 0) die('skip for ICU < 76.1'); ?> --FILE-- = 62.1 intl --SKIPIF-- = 62.1'); ?> += 0) die('skip for ICU < 76.1'); ?> --FILE-- Date: Wed, 23 Apr 2025 18:36:45 +0900 Subject: [PATCH 391/503] [skip ci] NEWS for #18317 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 6cf8816e8fc7f..bf4247ad1ca5b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.8 +- Date: + . Fixed bug GH-18076 (Since PHP 8, the date_sun_info() function returns + inaccurate sunrise and sunset times, but other calculated times are + correct) (JiriJozif). 24 Apr 2025, PHP 8.4.7 From 7e15a07feae72d47ad7b2fa8ea3a63fc59c95b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 23 Apr 2025 12:04:10 +0200 Subject: [PATCH 392/503] fileinfo: Remove `php_fileinfo` struct (#18398) * fileinfo: Remove `php_fileinfo` struct This is just a needless layer of indirection and requires an additional allocation. * fileinfo: Remove options field from `finfo_object` This was only required to restore the original options when options are given for `finfo_file()` or `finfo_buffer()`. This can more reliably be achieved using `magic_getflags()` and is therefore redundant. * fileinfo: Preserve error for uninitialized `finfo` objects --- ext/fileinfo/fileinfo.c | 93 +++++++++------------ ext/fileinfo/tests/finfo_uninitialized.phpt | 53 ++++++++++++ 2 files changed, 91 insertions(+), 55 deletions(-) create mode 100644 ext/fileinfo/tests/finfo_uninitialized.phpt diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index c0cc8877bf991..1dcc3346edfcc 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -36,17 +36,11 @@ #include "fopen_wrappers.h" /* needed for is_url */ #include "Zend/zend_exceptions.h" -/* {{{ macros and type definitions */ -typedef struct _php_fileinfo { - zend_long options; - struct magic_set *magic; -} php_fileinfo; - static zend_object_handlers finfo_object_handlers; zend_class_entry *finfo_class_entry; typedef struct _finfo_object { - php_fileinfo *ptr; + struct magic_set *magic; zend_object zo; } finfo_object; @@ -56,26 +50,12 @@ static inline finfo_object *php_finfo_fetch_object(zend_object *obj) { #define Z_FINFO_P(zv) php_finfo_fetch_object(Z_OBJ_P((zv))) -#define FILEINFO_FROM_OBJECT(finfo, object) \ -{ \ - finfo_object *obj = Z_FINFO_P(object); \ - finfo = obj->ptr; \ - if (!finfo) { \ - zend_throw_error(NULL, "Invalid finfo object"); \ - RETURN_THROWS(); \ - } \ -} - /* {{{ finfo_objects_free */ static void finfo_objects_free(zend_object *object) { finfo_object *intern = php_finfo_fetch_object(object); - if (intern->ptr) { - magic_close(intern->ptr->magic); - efree(intern->ptr); - } - + magic_close(intern->magic); zend_object_std_dtor(&intern->zo); } /* }}} */ @@ -153,7 +133,6 @@ PHP_FUNCTION(finfo_open) zend_long options = MAGIC_NONE; char *file = NULL; size_t file_len = 0; - php_fileinfo *finfo; zval *object = getThis(); char resolved_path[MAXPATHLEN]; zend_error_handling zeh; @@ -163,15 +142,10 @@ PHP_FUNCTION(finfo_open) } if (object) { - finfo_object *finfo_obj = Z_FINFO_P(object); - zend_replace_error_handling(EH_THROW, NULL, &zeh); - if (finfo_obj->ptr) { - magic_close(finfo_obj->ptr->magic); - efree(finfo_obj->ptr); - finfo_obj->ptr = NULL; - } + magic_close(Z_FINFO_P(object)->magic); + Z_FINFO_P(object)->magic = NULL; } if (file_len == 0) { @@ -199,13 +173,9 @@ PHP_FUNCTION(finfo_open) file = resolved_path; } - finfo = emalloc(sizeof(php_fileinfo)); + struct magic_set *magic = magic_open(options); - finfo->options = options; - finfo->magic = magic_open(options); - - if (finfo->magic == NULL) { - efree(finfo); + if (magic == NULL) { php_error_docref(NULL, E_WARNING, "Invalid mode '" ZEND_LONG_FMT "'.", options); if (object) { zend_restore_error_handling(&zeh); @@ -216,10 +186,9 @@ PHP_FUNCTION(finfo_open) RETURN_FALSE; } - if (magic_load(finfo->magic, file) == -1) { + if (magic_load(magic, file) == -1) { php_error_docref(NULL, E_WARNING, "Failed to load magic database at \"%s\"", file); - magic_close(finfo->magic); - efree(finfo); + magic_close(magic); if (object) { zend_restore_error_handling(&zeh); if (!EG(exception)) { @@ -230,14 +199,13 @@ PHP_FUNCTION(finfo_open) } if (object) { - finfo_object *obj; zend_restore_error_handling(&zeh); - obj = Z_FINFO_P(object); - obj->ptr = finfo; + finfo_object *obj = Z_FINFO_P(object); + obj->magic = magic; } else { zend_object *zobj = finfo_objects_new(finfo_class_entry); finfo_object *obj = php_finfo_fetch_object(zobj); - obj->ptr = finfo; + obj->magic = magic; RETURN_OBJ(zobj); } } @@ -260,18 +228,20 @@ PHP_FUNCTION(finfo_close) PHP_FUNCTION(finfo_set_flags) { zend_long options; - php_fileinfo *finfo; zval *self; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &self, finfo_class_entry, &options) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ - magic_setflags(finfo->magic, options); - finfo->options = options; + magic_setflags(Z_FINFO_P(self)->magic, options); RETURN_TRUE; } @@ -331,13 +301,17 @@ PHP_FUNCTION(finfo_file) zend_string *path = NULL; zend_long options = 0; zval *zcontext = NULL; - php_fileinfo *finfo = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OP|lr!", &self, finfo_class_entry, &path, &options, &zcontext) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); - struct magic_set *magic = finfo->magic; + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } + + struct magic_set *magic = Z_FINFO_P(self)->magic; if (UNEXPECTED(ZSTR_LEN(path) == 0)) { zend_argument_must_not_be_empty_error(2); @@ -349,6 +323,7 @@ PHP_FUNCTION(finfo_file) } /* Set options for the current file/buffer. */ + int old_options = magic_getflags(magic); if (options) { /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ @@ -356,9 +331,10 @@ PHP_FUNCTION(finfo_file) } const char *ret_val = php_fileinfo_from_path(magic, path, context); + /* Restore options */ if (options) { - magic_setflags(magic, finfo->options); + magic_setflags(magic, old_options); } if (UNEXPECTED(ret_val == NULL)) { @@ -375,16 +351,23 @@ PHP_FUNCTION(finfo_buffer) zend_string *buffer = NULL; zend_long options = 0; zval *dummy_context = NULL; - php_fileinfo *finfo = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OS|lr!", &self, finfo_class_entry, &buffer, &options, &dummy_context) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); - struct magic_set *magic = finfo->magic; + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } + + struct magic_set *magic = Z_FINFO_P(self)->magic; /* Set options for the current file/buffer. */ + int old_options = magic_getflags(magic); if (options) { + /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME + * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ magic_setflags(magic, options); } @@ -392,7 +375,7 @@ PHP_FUNCTION(finfo_buffer) /* Restore options */ if (options) { - magic_setflags(magic, finfo->options); + magic_setflags(magic, old_options); } if (UNEXPECTED(ret_val == NULL)) { diff --git a/ext/fileinfo/tests/finfo_uninitialized.phpt b/ext/fileinfo/tests/finfo_uninitialized.phpt new file mode 100644 index 0000000000000..533574c9c0dcd --- /dev/null +++ b/ext/fileinfo/tests/finfo_uninitialized.phpt @@ -0,0 +1,53 @@ +--TEST-- +Fileinfo uninitialized object +--EXTENSIONS-- +fileinfo +--FILE-- +newInstanceWithoutConstructor(); + +try { + var_dump(finfo_set_flags($finfo, FILEINFO_NONE)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->set_flags(FILEINFO_NONE)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(finfo_file($finfo, __FILE__)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->file(__FILE__)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(finfo_buffer($finfo, file_get_contents(__FILE__))); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->file(file_get_contents(__FILE__))); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object From 00affe43aaf0734f85b759ff0f790c316f604b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 23 Apr 2025 16:21:13 +0200 Subject: [PATCH 393/503] fileinfo: Show libmagic version with `.` in PHPInfo output (#18399) This makes the output in PHPInfo a little more readable. --- ext/fileinfo/fileinfo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 1dcc3346edfcc..143b8ba080fc5 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -115,10 +115,10 @@ ZEND_GET_MODULE(fileinfo) /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(fileinfo) { - char magic_ver[5]; + char magic_ver[15]; - (void)snprintf(magic_ver, 4, "%d", magic_version()); - magic_ver[4] = '\0'; + int raw_version = magic_version(); + (void)snprintf(magic_ver, sizeof(magic_ver), "%d.%d", raw_version / 100, raw_version % 100); php_info_print_table_start(); php_info_print_table_row(2, "fileinfo support", "enabled"); From d6e70e705323a50b616ffee9402245ab97de3e4e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 23 Apr 2025 17:44:23 +0200 Subject: [PATCH 394/503] Fix DOM tests for upcoming libxml2 serializer changes DOM HTML serializer will be closer compliant to HTML5 in the next libxml2 version, so the tests need to be adapted. Ref: https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/309 Closes GH-18406. --- ext/dom/tests/DOMElement_toggleAttribute.phpt | 6 +++--- ext/dom/tests/gh10234.phpt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/dom/tests/DOMElement_toggleAttribute.phpt b/ext/dom/tests/DOMElement_toggleAttribute.phpt index ed29be899dac2..b9e9989e1fe09 100644 --- a/ext/dom/tests/DOMElement_toggleAttribute.phpt +++ b/ext/dom/tests/DOMElement_toggleAttribute.phpt @@ -87,7 +87,7 @@ echo "Checking toggled namespace:\n"; var_dump($dom->documentElement->getAttribute('xmlns:anotheron')); ?> ---EXPECT-- +--EXPECTF-- Invalid Character Error --- Selected attribute tests (HTML) --- bool(false) @@ -95,10 +95,10 @@ bool(false) bool(true) - + bool(true) - + bool(false) diff --git a/ext/dom/tests/gh10234.phpt b/ext/dom/tests/gh10234.phpt index 5edc8fc6c1ff1..11d39cd625a79 100644 --- a/ext/dom/tests/gh10234.phpt +++ b/ext/dom/tests/gh10234.phpt @@ -55,7 +55,7 @@ $document->documentElement->textContent = "quote 'test'"; var_dump($document->documentElement->textContent); var_dump($document->saveHTML()); ?> ---EXPECT-- +--EXPECTF-- -- Attribute tests -- string(38) " " @@ -67,10 +67,10 @@ string(13) "hello & world" string(50) " " string(9) "hi" -string(54) " +string(%d) "hi<\/b>")%r> " string(12) "quote "test"" -string(45) " +string(%d) " " string(12) "quote 'test'" string(45) " From 0e1bbf9259f1b6afbab5cca6f9243c5de6f69d53 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 23 Apr 2025 17:44:17 +0100 Subject: [PATCH 395/503] Add PHP 8.4 to the list --- docs/release-process.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-process.md b/docs/release-process.md index 4c37d2b087390..eaaa8f76af8b3 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -6,6 +6,7 @@ repository available according to the release schedule. The release schedule for each version is published on the [PHP wiki](https://wiki.php.net): +- [PHP 8.4](https://wiki.php.net/todo/php84) - [PHP 8.3](https://wiki.php.net/todo/php83) - [PHP 8.2](https://wiki.php.net/todo/php82) - [PHP 8.1](https://wiki.php.net/todo/php81) From 7831f65f83ac63848c5b63ed4198cdad704a2ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 23 Apr 2025 18:57:32 +0200 Subject: [PATCH 396/503] fileinfo: Stop calling `finfo_close()` in tests (#18405) This function is a noop and will be proposed for deprecation. This patch removes the useless calls. --- ext/fileinfo/tests/bug79756.phpt | 1 - ext/fileinfo/tests/cve-2014-1943-mb.phpt | 2 -- ext/fileinfo/tests/cve-2014-1943.phpt | 2 -- ext/fileinfo/tests/cve-2014-3538-mb.phpt | 1 - ext/fileinfo/tests/cve-2014-3538-nojit.phpt | 1 - ext/fileinfo/tests/cve-2014-3538.phpt | 1 - ext/fileinfo/tests/finfo_buffer_basic-mb.phpt | 1 - ext/fileinfo/tests/finfo_buffer_basic.phpt | 1 - ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt | 2 -- ext/fileinfo/tests/finfo_set_flags_basic.phpt | 2 -- ext/fileinfo/tests/finfo_upstream.phpt | 1 - 11 files changed, 15 deletions(-) diff --git a/ext/fileinfo/tests/bug79756.phpt b/ext/fileinfo/tests/bug79756.phpt index b4ea28baaa9b2..ad5478b62de8e 100644 --- a/ext/fileinfo/tests/bug79756.phpt +++ b/ext/fileinfo/tests/bug79756.phpt @@ -7,7 +7,6 @@ fileinfo $filename = __DIR__ . '/bug79756.xls'; $finfo = finfo_open(FILEINFO_MIME); $mime = finfo_file($finfo, $filename); -finfo_close($finfo); echo $mime; ?> --EXPECT-- diff --git a/ext/fileinfo/tests/cve-2014-1943-mb.phpt b/ext/fileinfo/tests/cve-2014-1943-mb.phpt index 9dd4a9ec18a5a..01cf70b811bea 100644 --- a/ext/fileinfo/tests/cve-2014-1943-mb.phpt +++ b/ext/fileinfo/tests/cve-2014-1943-mb.phpt @@ -15,13 +15,11 @@ $m = "0 byte x\n". file_put_contents($fd, $a); $fi = finfo_open(FILEINFO_NONE); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); file_put_contents($fd, $b); file_put_contents($fm, $m); $fi = finfo_open(FILEINFO_NONE, $fm); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); ?> Done --CLEAN-- diff --git a/ext/fileinfo/tests/cve-2014-1943.phpt b/ext/fileinfo/tests/cve-2014-1943.phpt index 35f66148ae79c..1aee196d16ffc 100644 --- a/ext/fileinfo/tests/cve-2014-1943.phpt +++ b/ext/fileinfo/tests/cve-2014-1943.phpt @@ -15,13 +15,11 @@ $m = "0 byte x\n". file_put_contents($fd, $a); $fi = finfo_open(FILEINFO_NONE); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); file_put_contents($fd, $b); file_put_contents($fm, $m); $fi = finfo_open(FILEINFO_NONE, $fm); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); ?> Done --CLEAN-- diff --git a/ext/fileinfo/tests/cve-2014-3538-mb.phpt b/ext/fileinfo/tests/cve-2014-3538-mb.phpt index e6c63e35ac852..3b158a26b7264 100644 --- a/ext/fileinfo/tests/cve-2014-3538-mb.phpt +++ b/ext/fileinfo/tests/cve-2014-3538-mb.phpt @@ -19,7 +19,6 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); if ($t < 3) { echo "Ok\n"; } else { diff --git a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt index 2010d538da951..73ecd09561d84 100644 --- a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt +++ b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt @@ -23,7 +23,6 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); if ($t < 1.5) { echo "Ok\n"; } else { diff --git a/ext/fileinfo/tests/cve-2014-3538.phpt b/ext/fileinfo/tests/cve-2014-3538.phpt index f15e745fc05d3..d19278d1dc325 100644 --- a/ext/fileinfo/tests/cve-2014-3538.phpt +++ b/ext/fileinfo/tests/cve-2014-3538.phpt @@ -19,7 +19,6 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); if ($t < 1.5) { echo "Ok\n"; } else { diff --git a/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt b/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt index 7426c909d9763..0ed6d48c803cb 100644 --- a/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt +++ b/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt @@ -27,7 +27,6 @@ foreach( $options as $option ) { foreach( $buffers as $string ) { var_dump( finfo_buffer( $finfo, $string, $option ) ); } - finfo_close( $finfo ); } ?> diff --git a/ext/fileinfo/tests/finfo_buffer_basic.phpt b/ext/fileinfo/tests/finfo_buffer_basic.phpt index e338583fab702..6a6e6a7a862cb 100644 --- a/ext/fileinfo/tests/finfo_buffer_basic.phpt +++ b/ext/fileinfo/tests/finfo_buffer_basic.phpt @@ -27,7 +27,6 @@ foreach( $options as $option ) { foreach( $buffers as $string ) { var_dump( finfo_buffer( $finfo, $string, $option ) ); } - finfo_close( $finfo ); } ?> diff --git a/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt b/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt index f366972b613e1..a4d723f86c9ca 100644 --- a/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt +++ b/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt @@ -12,8 +12,6 @@ echo "*** Testing finfo_set_flags() : basic functionality ***\n"; var_dump( finfo_set_flags( $finfo, FILEINFO_NONE ) ); var_dump( finfo_set_flags( $finfo, FILEINFO_SYMLINK ) ); -finfo_close( $finfo ); - // OO way $finfo = new finfo( FILEINFO_NONE, $magicFile ); var_dump( $finfo->set_flags( FILEINFO_MIME ) ); diff --git a/ext/fileinfo/tests/finfo_set_flags_basic.phpt b/ext/fileinfo/tests/finfo_set_flags_basic.phpt index 948031a0b8006..db71447ae2393 100644 --- a/ext/fileinfo/tests/finfo_set_flags_basic.phpt +++ b/ext/fileinfo/tests/finfo_set_flags_basic.phpt @@ -12,8 +12,6 @@ echo "*** Testing finfo_set_flags() : basic functionality ***\n"; var_dump( finfo_set_flags( $finfo, FILEINFO_NONE ) ); var_dump( finfo_set_flags( $finfo, FILEINFO_SYMLINK ) ); -finfo_close( $finfo ); - // OO way $finfo = new finfo( FILEINFO_NONE, $magicFile ); var_dump( $finfo->set_flags( FILEINFO_MIME ) ); diff --git a/ext/fileinfo/tests/finfo_upstream.phpt b/ext/fileinfo/tests/finfo_upstream.phpt index ef5ec17b03706..2a28bd7f776c0 100644 --- a/ext/fileinfo/tests/finfo_upstream.phpt +++ b/ext/fileinfo/tests/finfo_upstream.phpt @@ -18,7 +18,6 @@ foreach($lst as $p) { if ($i !== $exp) { echo "'$p' failed\nexp: '$exp'\ngot: '$i'\n"; } - finfo_close($finfo); } echo "==DONE=="; From 54e662c6f51c64571b02157f5b777c057e696280 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 23 Apr 2025 17:53:48 +0200 Subject: [PATCH 397/503] Revert "Port XML_GetCurrentByteIndex to public APIs" This reverts commit 8dc799aac7b3c5f7be639c0f15d3f294a7b194a7. Originally, this was going to be deprecated in libxml2 2.14, but this didn't end up happening in the end, and the replacement function that we used got deprecated instead. So fix the deprecation warning by reverting to the original code. Closes GH-18407. --- ext/xml/compat.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 5f55dc62b3687..a3283f71f7552 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -709,21 +709,8 @@ XML_GetCurrentColumnNumber(XML_Parser parser) PHP_XML_API int XML_GetCurrentByteIndex(XML_Parser parser) { - /* We have to temporarily disable the encoder to satisfy the note from the manual: - * "This function returns byte index according to UTF-8 encoded text disregarding if input is in another encoding." - * Although that should probably be corrected at one point? (TODO) */ - xmlCharEncodingHandlerPtr encoder = NULL; - xmlParserInputPtr input = parser->parser->input; - if (input->buf) { - encoder = input->buf->encoder; - input->buf->encoder = NULL; - } - long result = xmlByteConsumed(parser->parser); - if (encoder) { - input->buf->encoder = encoder; - } - /* TODO: at one point this should return long probably to make sure that files greater than 2 GiB are handled correctly. */ - return (int) result; + return parser->parser->input->consumed + + (parser->parser->input->cur - parser->parser->input->base); } PHP_XML_API int From b5081339e9c3f1c77829de3cac7b34098e4b83c4 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 24 Apr 2025 11:26:17 +0200 Subject: [PATCH 398/503] [skip ci] Increase tolerance for cve-2014-3538 tests These regularly fail with "Failed, time=1.5x". --- ext/fileinfo/tests/cve-2014-3538-nojit.phpt | 2 +- ext/fileinfo/tests/cve-2014-3538.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt index 2010d538da951..3fe21168ab8fc 100644 --- a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt +++ b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt @@ -24,7 +24,7 @@ $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; finfo_close($fi); -if ($t < 1.5) { +if ($t < 2) { echo "Ok\n"; } else { printf("Failed, time=%.2f\n", $t); diff --git a/ext/fileinfo/tests/cve-2014-3538.phpt b/ext/fileinfo/tests/cve-2014-3538.phpt index c5dba2b428c5f..2e222a6c49901 100644 --- a/ext/fileinfo/tests/cve-2014-3538.phpt +++ b/ext/fileinfo/tests/cve-2014-3538.phpt @@ -22,7 +22,7 @@ $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; finfo_close($fi); -if ($t < 1.5) { +if ($t < 2) { echo "Ok\n"; } else { printf("Failed, time=%.2f\n", $t); From 090b1cf229f502c70b90589a9f4f050cd5c4fcfa Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Thu, 24 Apr 2025 18:53:11 +0300 Subject: [PATCH 399/503] [ci skip] Update PHP Release Process (#18342) --- docs/release-process.md | 55 +++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/docs/release-process.md b/docs/release-process.md index eaaa8f76af8b3..5d603a22f078e 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -74,7 +74,7 @@ releases. > When you are unsure about anything, ask a previous RM before proceeding. > Ideally, make sure a previous RM is available to answer questions during > the first few releases of your version. For the steps related to the - > `web-php`, `web-qa`, and `web-php-distributions` repositories, try to have + > `web-php` and `web-php-distributions` repositories, try to have > someone from the webmaster team on hand. 5. Verify the tags to be extra sure everything was tagged properly. @@ -360,11 +360,10 @@ slightly different steps. We'll call attention where the steps differ. ## Announcing a non-stable release (alpha/beta/RC) -1. Switch to your local clone of the `web-qa` repository and update the +1. Switch to your local clone of the `web-php` repository and update the information in the `$QA_RELEASES` array in `include/release-qa.php`. Follow the documentation in the file for editing the QA release information. - See also [Announce 8.1.0RC3][] and [8.1.6RC1][] for examples. Add, commit, and push your changes, when finished. @@ -717,20 +716,7 @@ slightly different steps. We'll call attention where the steps differ. ```shell ./bin/news2html 'https://github.com/php/php-src/raw/php-X.Y.Z/NEWS' 'X.Y.Z' 'ChangeLog-X.php' ``` - -9. Review all the changes in `web-php`, commit, and push them. - - ```shell - git add -p - git add archive/entries/*.xml releases/*.php - git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.Z" - git push upstream master - ``` - - See [Announce PHP 8.1.6][] for an example commit. - -10. Switch to your local clone of the `web-qa` repository and update the - information in the `$QA_RELEASES` array in `include/release-qa.php`. +8. Update the information in the `$QA_RELEASES` array in `include/release-qa.php`. The array probably contains information about the RC released two weeks ago in preparation for the current release. Since the current release is now GA, @@ -738,18 +724,20 @@ slightly different steps. We'll call attention where the steps differ. It is sufficient to set the `number` property for the release to `0` to stop displaying the RC build on the QA website. You may also remove the - sha256 hashes for the RC tarballs, but it's not necessary. For an example, - see [PHP 8.1.6 released][]. + sha256 hashes for the RC tarballs, but it's not necessary. - Add, commit, and push your changes, when finished. +9. Review all the changes in `web-php`, commit, and push them. ```shell git add -p - git commit --gpg-sign=YOURKEYID -m "PHP X.Y.Z released" + git add archive/entries/*.xml releases/*.php + git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.Z" git push upstream master ``` -11. 🚨 **Before sending announcement emails, check to make sure the websites have + See [Announce PHP 8.1.6][] for an example commit. + +10. 🚨 **Before sending announcement emails, check to make sure the websites have synced.** * Make sure the tarballs are available from, e.g., @@ -761,8 +749,8 @@ slightly different steps. We'll call attention where the steps differ. e.g., https://www.php.net/ChangeLog-8.php * Is there a release page for the new version? e.g., `https://www.php.net/releases/X_Y_Z.php` - * Does the RC for this version still appear on the QA home page? - https://qa.php.net + * Does the RC for this version still appear on the Release Candidate Builds page? + https://www.php.net/release-candidates.php Keep in mind it may take up to an hour for the websites to sync. @@ -987,21 +975,22 @@ volunteers to begin the selection process for the next release managers. ## New release manager checklist -1. Request membership to the +1. Fill out [the form](https://www.php.net/git-php.php) + to get a PHP account (if you don't already have one). + +2. Request membership to the [release managers group](https://github.com/orgs/php/teams/release-managers) on GitHub. -2. Subscribe to the php-announce@lists.php.net mailing list by emailing +3. Subscribe to the php-announce@lists.php.net mailing list by emailing php-announce+subscribe@lists.php.net -3. Email systems@php.net to get setup for access to downloads.php.net, to be +4. Email systems@php.net to get setup for access to downloads.php.net, to be added to the release-managers@php.net distribution list, and to be added to the moderators for php-announce@lists.php.net so you are able to moderate your release announcements. Provide the following information in a single email: - - Preferred Unix username (will also become part of location to download RCs, - such as `https://downloads.php.net/~derick/`). - An SSH public key, preferably a new unique one for PHP systems and projects. - Read [Machine Access](https://wiki.php.net/systems#machine_access) to set @@ -1022,7 +1011,7 @@ volunteers to begin the selection process for the next release managers. > "[Send emails from a different address or alias][]." -4. Create a [GPG key][] for your @php.net address. +5. Create a [GPG key][] for your @php.net address. > 💡 **Tip** \ > If you're new to GPG, follow GitHub's instructions for @@ -1087,11 +1076,10 @@ volunteers to begin the selection process for the next release managers. git push ``` -5. Make sure you have the following repositories cloned locally: +6. Make sure you have the following repositories cloned locally: * https://github.com/php/php-src * https://github.com/php/web-php - * https://github.com/php/web-qa * https://github.com/php/web-php-distributions @@ -1106,13 +1094,10 @@ volunteers to begin the selection process for the next release managers. [Update NEWS for PHP 8.2.0RC6]: https://github.com/php/php-src/commit/4ccc414961a70200d638ca281a35f893226d74e2 [PHP 8.3 is now for PHP 8.3.21-dev]: https://github.com/php/php-src/commit/b57f425cfe20a11003253427424cc0517483550b [GitHub command line tool]: https://cli.github.com -[Announce 8.1.0RC3]: https://github.com/php/web-qa/commit/f264b711fd3827803b79bbb342959eae57ea502b -[8.1.6RC1]: https://github.com/php/web-qa/commit/e6d61ad7a9d8be0b1cd159af29f3b9cbdde33384 [merged upwards as usual]: https://wiki.php.net/vcs/gitworkflow [Update versions for PHP 8.1.7]: https://github.com/php/php-src/commit/d35e577a1bd0b35b9386cea97cddc73fd98eed6d [Update NEWS for PHP 8.1.7]: https://github.com/php/php-src/commit/b241f07f52ca9f87bf52be81817f475e6e727439 [Announce PHP 8.1.6]: https://github.com/php/web-php/commit/9f796a96c65f07e45845ec248933bfb0010b94a9 -[PHP 8.1.6 released]: https://github.com/php/web-qa/commit/bff725f8373cf6fd9d97ba62a8517b19721a4c2e [feature freeze]: https://en.wikipedia.org/wiki/Freeze_(software_engineering) [Prepare for PHP 8.2]: https://github.com/php/php-src/commit/1c33ddb5e5598c5385c4c965992c6e031fd00dd6 [Prepare for PHP 8.2 (bis)]: https://github.com/php/php-src/commit/a93e12f8a6dfc23e334339317c97aa35356db821 From 32e091260aeb6192caa760e8cf87837f63d1c66a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 20 Apr 2025 22:57:58 +0200 Subject: [PATCH 400/503] Fix GH-17403: Potential deadlock when putenv fails Closes GH-18368. --- NEWS | 3 +++ ext/standard/basic_functions.c | 1 + 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index bf57077f4544c..409972a1fe9f5 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ PHP NEWS inaccurate sunrise and sunset times, but other calculated times are correct) (JiriJozif). +- Standard: + . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) + 08 May 2025, PHP 8.3.21 - Core: diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 99d92af167f0e..d2a99fccc95fe 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -849,6 +849,7 @@ PHP_FUNCTION(putenv) #endif RETURN_TRUE; } else { + tsrm_env_unlock(); free(pe.putenv_string); zend_string_release(pe.key); #ifdef PHP_WIN32 From 6c0578d31c341b505983fc5b63cab04c540fa86a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 21 Apr 2025 13:32:38 +0200 Subject: [PATCH 401/503] Improve performance of urldecode() and rawurldecode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two hot spots on my machines: 1. We copy the string because the internal PHP API works in-place. 2. The conversion of hex characters is slow due to going through the C locale handling. This patch resolves the first hot spots by introducing 2 new internal APIs that avoid the redundant copy and allocate an empty string upfront. The second hotspot is resolved by having a specialised htoi handler. For the following benchmark: ```php $encoded = "Hello%20World%21+This%20is%20a%20test%3A%20%40%23%24%25%5E%26*%28%29"; for ($i=0;$i<2000000;$i++) { rawurldecode($encoded); urldecode($encoded); } ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 364.8 ms ± 3.7 ms [User: 359.9 ms, System: 3.3 ms] Range (min … max): 359.9 ms … 372.0 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 565.5 ms ± 4.9 ms [User: 561.8 ms, System: 2.5 ms] Range (min … max): 560.7 ms … 578.2 ms 10 runs Summary ./sapi/cli/php x.php ran 1.55 ± 0.02 times faster than ./sapi/cli/php_old x.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 708.8 ms ± 6.1 ms [User: 701.4 ms, System: 6.3 ms] Range (min … max): 701.9 ms … 722.3 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 1.311 s ± 0.019 s [User: 1.300 s, System: 0.008 s] Range (min … max): 1.281 s … 1.348 s 10 runs Summary ./sapi/cli/php x.php ran 1.85 ± 0.03 times faster than ./sapi/cli/php_old x.php ``` Closes GH-18378. --- UPGRADING | 1 + UPGRADING.INTERNALS | 4 +++ ext/standard/url.c | 69 +++++++++++++++++++++++++++------------------ ext/standard/url.h | 2 ++ 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/UPGRADING b/UPGRADING index 40645a28ac600..68f7d20a7f32f 100644 --- a/UPGRADING +++ b/UPGRADING @@ -476,6 +476,7 @@ PHP 8.5 UPGRADE NOTES - Standard: . Improved performance of array functions with callbacks (array_find, array_filter, array_map, usort, ...). + . Improved performance of urlencode() and rawurlencode(). - XMLReader: . Improved property access performance. diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 56c7535158460..7c7f093e50cce 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -61,6 +61,10 @@ PHP 8.5 INTERNALS UPGRADE NOTES is still valid. This is useful when a GC cycle is collected and the database object can be destroyed prior to destroying the statement. +- ext/standard + . Added php_url_decode_ex() and php_raw_url_decode_ex() that unlike their + non-ex counterparts do not work in-place. + ======================== 4. OpCode changes ======================== diff --git a/ext/standard/url.c b/ext/standard/url.c index 3d704b0140ca9..da2ddea067314 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -411,21 +411,24 @@ PHP_FUNCTION(parse_url) } /* }}} */ +/* https://stackoverflow.com/questions/34365746/whats-the-fastest-way-to-convert-hex-to-integer-in-c */ +static unsigned int php_htoi_single(unsigned char x) +{ + ZEND_ASSERT((x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F') || (x >= '0' && x <= '9')); + return 9 * (x >> 6) + (x & 0xf); +} + /* {{{ php_htoi */ -static int php_htoi(char *s) +static int php_htoi(const char *s) { int value; - int c; + unsigned char c; c = ((unsigned char *)s)[0]; - if (isupper(c)) - c = tolower(c); - value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16; + value = php_htoi_single(c) * 16; c = ((unsigned char *)s)[1]; - if (isupper(c)) - c = tolower(c); - value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10; + value += php_htoi_single(c); return (value); } @@ -572,28 +575,27 @@ PHP_FUNCTION(urldecode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - out_str = zend_string_init(ZSTR_VAL(in_str), ZSTR_LEN(in_str), 0); - ZSTR_LEN(out_str) = php_url_decode(ZSTR_VAL(out_str), ZSTR_LEN(out_str)); + out_str = zend_string_alloc(ZSTR_LEN(in_str), false); + ZSTR_LEN(out_str) = php_url_decode_ex(ZSTR_VAL(out_str), ZSTR_VAL(in_str), ZSTR_LEN(in_str)); RETURN_NEW_STR(out_str); } /* }}} */ -/* {{{ php_url_decode */ -PHPAPI size_t php_url_decode(char *str, size_t len) +PHPAPI size_t php_url_decode_ex(char *dest, const char *src, size_t src_len) { - char *dest = str; - char *data = str; + char *dest_start = dest; + const char *data = src; - while (len--) { + while (src_len--) { if (*data == '+') { *dest = ' '; } - else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + else if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; - len -= 2; + src_len -= 2; } else { *dest = *data; } @@ -601,7 +603,13 @@ PHPAPI size_t php_url_decode(char *str, size_t len) dest++; } *dest = '\0'; - return dest - str; + return dest - dest_start; +} + +/* {{{ php_url_decode */ +PHPAPI size_t php_url_decode(char *str, size_t len) +{ + return php_url_decode_ex(str, str, len); } /* }}} */ @@ -634,25 +642,24 @@ PHP_FUNCTION(rawurldecode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - out_str = zend_string_init(ZSTR_VAL(in_str), ZSTR_LEN(in_str), 0); - ZSTR_LEN(out_str) = php_raw_url_decode(ZSTR_VAL(out_str), ZSTR_LEN(out_str)); + out_str = zend_string_alloc(ZSTR_LEN(in_str), false); + ZSTR_LEN(out_str) = php_raw_url_decode_ex(ZSTR_VAL(out_str), ZSTR_VAL(in_str), ZSTR_LEN(in_str)); RETURN_NEW_STR(out_str); } /* }}} */ -/* {{{ php_raw_url_decode */ -PHPAPI size_t php_raw_url_decode(char *str, size_t len) +PHPAPI size_t php_raw_url_decode_ex(char *dest, const char *src, size_t src_len) { - char *dest = str; - char *data = str; + char *dest_start = dest; + const char *data = src; - while (len--) { - if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + while (src_len--) { + if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; - len -= 2; + src_len -= 2; } else { *dest = *data; } @@ -660,7 +667,13 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len) dest++; } *dest = '\0'; - return dest - str; + return dest - dest_start; +} + +/* {{{ php_raw_url_decode */ +PHPAPI size_t php_raw_url_decode(char *str, size_t len) +{ + return php_raw_url_decode_ex(str, str, len); } /* }}} */ diff --git a/ext/standard/url.h b/ext/standard/url.h index 4126ee6c6db40..5c531c0086a20 100644 --- a/ext/standard/url.h +++ b/ext/standard/url.h @@ -33,7 +33,9 @@ PHPAPI php_url *php_url_parse(char const *str); PHPAPI php_url *php_url_parse_ex(char const *str, size_t length); PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port); PHPAPI size_t php_url_decode(char *str, size_t len); /* return value: length of decoded string */ +PHPAPI size_t php_url_decode_ex(char *dest, const char *src, size_t src_len); PHPAPI size_t php_raw_url_decode(char *str, size_t len); /* return value: length of decoded string */ +PHPAPI size_t php_raw_url_decode_ex(char *dest, const char *src, size_t src_len); PHPAPI zend_string *php_url_encode(char const *s, size_t len); PHPAPI zend_string *php_raw_url_encode(char const *s, size_t len); From 6c09c167efe557e11f266f70a94767e6bcf92df8 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Fri, 25 Apr 2025 08:26:51 +0900 Subject: [PATCH 402/503] removed (#18414) --- Zend/zend_hash.c | 1 - Zend/zend_types.h | 1 - 2 files changed, 2 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 8bddb0c208835..66cfb250d1fec 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -30,7 +30,6 @@ #if defined(__AVX2__) # include #elif defined( __SSE2__) -# include # include #endif diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 7676a1d42a5f4..4a6d00b9d73ea 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -28,7 +28,6 @@ #include #ifdef __SSE2__ -# include # include #endif #if defined(__AVX2__) From ec288b1b077ddf0673b672b22db37411741657f0 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 23 Apr 2025 17:07:23 +0100 Subject: [PATCH 403/503] Convert https://qa.php.net/write-test.php and https://qa.php.net/phpt_details.php --- docs/source/miscellaneous/writing-tests.rst | 1673 +++++++++++++++++++ 1 file changed, 1673 insertions(+) create mode 100644 docs/source/miscellaneous/writing-tests.rst diff --git a/docs/source/miscellaneous/writing-tests.rst b/docs/source/miscellaneous/writing-tests.rst new file mode 100644 index 0000000000000..e16e905beda93 --- /dev/null +++ b/docs/source/miscellaneous/writing-tests.rst @@ -0,0 +1,1673 @@ +############ + Test Files +############ + +****************** + phpt Test Basics +****************** + +The first thing you need to know about tests is that we need more!!! Although PHP works just great +99.99% of the time, not having a very comprehensive test suite means that we take more risks every +time we add to or modify the PHP implementation. The second thing you need to know is that if you +can write PHP you can write tests. Thirdly — we are a friendly and welcoming community, don't be +scared about writing to (php-qa@lists.php.net) — we won't bite! + +So what are phpt tests? + + A phpt test is a little script used by the php internal and quality assurance teams to test PHP's + functionality. It can be used with new releases to make sure they can do all the things that + previous releases can, or to help find bugs in current releases. By writing phpt tests you are + helping to make PHP more stable. + +What skills are needed to write a phpt test? + + All that is really needed to write a phpt test is a basic understanding of the PHP language, a + text editor, and a way to get the results of your code. That is it. So if you have been writing + and running PHP scripts already — you have everything you need. + +What do you write phpt tests on? + + Basically you can write a phpt test on one of the various php functions available. You can write + a test on a basic language function (a string function or an array function) , or a function + provided by one of PHP's numerous extensions (a mysql function or a image function or a mcrypt + function). + + You can find out what functions already have phpt tests by looking in the `html version + `_ of the git repository (``ext/standard/tests/`` is a good place + to start looking — though not all the tests currently written are in there). + + If you want more guidance than that you can always ask the PHP Quality Assurance Team on their + mailing list (php-qa@lists.php.net) where they would like you to direct your attentions. + +How is a phpt test is used? + + When a test is called by the ``run-tests.php`` script it takes various parts of the phpt file to + name and create a .php file. That .php file is then executed. The output of the .php file is then + compared to a different section of the phpt file. If the output of the script "matches" the + output provided in the phpt script — it passes. + +What should a phpt test do? + + Basically — it should try and break the PHP function. It should check not only the functions + normal parameters, but it should also check edge cases. Intentionally generating an error is + allowed and encouraged. + +******************** + Writing phpt Tests +******************** + +Naming Conventions +================== + +Phpt tests follow a very strict naming convention. This is done to easily identify what each phpt +test is for. Tests should be named according to the following list: + +Tests for bugs + bug.phpt (bug17123.phpt) + +Tests for a function's basic behaviour + _basic.phpt (dba_open_basic.phpt) + +Tests for a function's error behaviour + _error.phpt (dba_open_error.phpt) + +Tests for variations in a function's behaviour + _variation.phpt (dba_open_variation.phpt) + +General tests for extensions + .phpt (dba_003.phpt) + +The convention of using _basic, _error and _variation was introduced when we found that writing a +single test case for each function resulted in unacceptably large test cases. It's quite hard to +debug problems when the test case generates 100s of lines of output. + +The "basic" test case for a function should just address the single most simple thing that the +function is designed to do. For example, if writing a test for the sin() function a basic test would +just be to check that sin() returns the correct values for some known angles — eg 30, 90, 180. + +The "error" tests for a function are test cases which are designed to provoke errors, warnings or +notices. There can be more than one error case, if so the convention is to name the test cases +mytest_error1.phpt, mytest_error2.phpt and so on. + +The "variation" tests are any tests that don't fit into "basic" or "error" tests. For example one +might use a variation tests to test boundary conditions. + +How big is a test case? +======================= + +Small. Really — the smaller the better, a good guide is no more than 10 lines of output. The reason +for this is that if we break something in PHP and it breaks your test case we need to be able to +find out quite quickly what we broke, going through 1000s of line of test case output is not easy. +Having said that it's sometimes just not practical to stay within the 10 line guideline, in this +case you can help a lot by commenting the output. You may find plenty of much longer tests in PHP - +the small tests message is something that we learnt over time, in fact we are slowly going through +and splitting tests up when we need to. + +Comments +======== + +Comments help. Not an essay — just a couple of lines on what the objective of the test is. It may +seem completely obvious to you as you write it, but it might not be to someone looking at it later +on. + +Basic Format +============ + +A test must contain the sections TEST, FILE and either EXPECT or EXPECTF at a minimum. The example +below illustrates a minimal test. + +*ext/standard/tests/strings/strtr.phpt* + +.. code:: php + + --TEST-- + strtr() function — basic test for strtr() + --FILE-- + "hi", "hi"=>"hello", "a"=>"A", "world"=>"planet"); + var_dump(strtr("# hi all, I said hello world! #", $trans)); + ?> + --EXPECT-- + string(32) "# hello All, I sAid hi planet! #" + +As you can see the file is divided into several sections. The TEST section holds a one line title of +the phpt test, this should be a simple description and shouldn't ever excede one line, if you need +to write more explanation add comments in the body of the test case. The phpt files name is used +when generating a .php file. The FILE section is used as the body of the .php file, so don't forget +to open and close your php tags. The EXPECT section is the part used as a comparison to see if the +test passes. It is a good idea to generate output with var_dump() calls. + +PHPT structure details +====================== + +A phpt test can have many more parts than just the minimum. In fact some of the mandatory parts have +alternatives that may be used if the situation warrants it. The phpt sections are documented here. + +Analyzing failing tests +======================= + +While writing tests you will probably run into tests not passing while you think they should. The +'make test' command provides you with debug information. Several files will be added per test in the +same directory as the .phpt file itself. Considering your test file is named foo.phpt, these files +provide you with information that can help you find out what went wrong: + +foo.diff + + A diff file between the expected output (be it in EXPECT, EXPECTF or another option) and the + actual output. + +foo.exp + + The expected output. + +foo.log + + A log containing expected output, actual output and results. Most likely very similar to info in + the other files. + +foo.out + + The actual output of your .phpt test part. + +foo.php + + The php code that was executed for this test. + +foo.sh + + An executable file that executes the test for you as it was executed during failure. + +Testing your test cases +======================= + +Most people who write tests for PHP don't have access to a huge number of operating systems but the +tests are run on every system that runs PHP. It's good to test your test on as many platforms as you +can — Linux and Windows are the most important, it's increasingly important to make sure that tests +run on 64 bit as well as 32 bit platforms. If you only have access to one operating system — don't +worry, if you have karma, commit the test but watch php-qa@lists.php.net for reports of failures on +other platforms. If you don't have karma to commit have a look at the next section. + +When you are testing your test case it's really important to make sure that you clean up any +temporary resources (eg files) that you used in the test. There is a special ``--CLEAN--`` section +to help you do this — see here. + +Another good check is to look at what lines of code in the PHP source your test case covers. This is +easy to do, there are some instructions on the PHP Wiki. + +What should I do with my test case when I've written and tested it? +=================================================================== + +The next step is to get someone to review it. If it's short you can paste it into a note and send it +to php-qa@lists.php.net. If the test is a bit too long for that then put it somewhere were people +can download it (pastebin is sometimes used). Appending tests to notes as files doesn't work well - +so please don't do that. Your note to php-qa@lists.php.net should say what level of PHP you have +tested it on and what platform(s) you've run it on. Someone from the PHP QA group will review your +test and reply to you. They may ask for some changes or suggest better ways to do things, or they +may commit it to PHP. + +Writing Portable PHP Tests +========================== + +Writing portable tests can be hard if you don't have access to all the many platforms that PHP can +run on. Do your best. If in doubt, don't disable a test. It is better that the test runs in as many +environments as possible. + +If you know a new test won't run in a specific environment, try to write the complementary test for +that environment. + +Make sure sets of data are consistently ordered. SQL queries are not guaranteed to return results in +the same order unless an ORDER BY clause is used. Directory listings are another example that can +vary: use an appropriate PHP function to sort them befor printing. Both of these examples have +affected PHP tests in the past. + +Make sure that any test touching parsing or display of dates uses a hard-defined timezone - +preferable 'UTC'. It is important tha this is defined in the file section using: + +.. code:: php + + date_default_timezone_set('UTC'); + +and not in the INI section. This is because of the order in which settings are checked which is: + +.. code:: + + date_default_timezone_set() -> TZ environmental -> INI setting -> System Setting + +If a TZ environmental varaibale is found the INI setting will be ignored. + +Tests that run, or only have have matching EXPECT output, on 32bit platforms can use a SKIPIF +section like: + +.. code:: php + + --SKIPIF-- + + +Tests for 64bit platforms can use: + +.. code:: php + + --SKIPIF-- + + +To run a test only on Windows: + +.. code:: php + + --SKIPIF-- + + +To run a test only on Linux: + +.. code:: php + + --SKIPIF-- + + +To skip a test on Mac OS X Darwin: + +.. code:: php + + --SKIPIF-- + + +********** + Examples +********** + +EXPECTF +======= + +/ext/standard/tests/strings/str_shuffle.phpt is a good example for using EXPECTF instead of EXPECT. +From time to time the algorithm used for shuffle changed and sometimes the machine used to execute +the code has influence on the result of shuffle. But it always returns a three character string +detectable by %s (that matches any string until the end of the line). Other scan-able forms are %a +for any amount of chars (at least one), %i for integers, %d for numbers only, %f for floating point +values, %c for single characters, %x for hexadecimal values, %w for any number of whitespace +characters and %e for DIRECTORY_SEPARATOR ('\' or '/'). + +See also EXPECTF details + +*/ext/standard/tests/strings/str_shuffle.phpt* + +.. code:: php + + --TEST-- + Testing str_shuffle. + --FILE-- + + --EXPECTF-- + string(3) "%s" + string(3) "123" + +EXPECTREGEX +=========== + +/ext/standard/tests/strings/strings001.phpt is a good example for using EXPECTREGEX instead of +EXPECT. This test also shows that in EXPECTREGEX some characters need to be escaped since otherwise +they would be interpreted as a regular expression. + +*/ext/standard/tests/strings/strings001.phpt* + +.. code:: php + + --TEST-- + Test whether strstr() and strrchr() are binary safe. + --FILE-- + + --EXPECTREGEX-- + string\(18\) \"nica\x00turska panica\" + string\(19\) \" nica\x00turska panica\" + +EXTENSIONS +========== + +Some tests depend on PHP extensions that may be unavailable. These extensions should be listed in +the EXTENSIONS section. If an extension is missing, PHP will try to find it in a shared module and +skip the test if it's not there. + +*/ext/sodium/tests/crypto_scalarmult.phpt* + +.. code:: php + + --TEST-- + Check for libsodium scalarmult + --EXTENSIONS-- + sodium + --FILE-- + + --FILE-- + [snip] + +Test script and SKIPIF code should be directly written into \*.phpt. However, it is recommended to +use include files when more test scripts depend on the same SKIPIF code or when certain test files +need the same values for some input. + +Note: no file used by any test should have one of the following extensions: ".php", ".log", ".mem", +".exp", ".out" or ".diff". When you use an include file for the SKIPIF section it should be named +"skipif.inc" and an include file used in the FILE section of many tests should be named "test.inc". + +************* + Final Notes +************* + +Cleaning up after running a test +================================ + +Sometimes test cases create files or directories as part of the test case and it's important to +remove these after the test ends, the ``--CLEAN--`` section is provided to help with this. + +The PHP code in the ``--CLEAN--`` section is executed separately from the code in the ``--FILE--`` +section. For example, this code: + +.. code:: php + + --TEST-- + Will fail to clean up + --FILE-- + + --CLEAN-- + + --EXPECT-- + +will not remove the temporary file because the variable $temp_filename is not defined in the +``--CLEAN--`` section. + +Here is a better way to write the code: + +.. code:: php + + --TEST-- + This will remove temporary files + --FILE-- + + --CLEAN-- + + --EXPECT-- + +Note the use of the __DIR__ construct which will ensure that the temporary file is created in the +same directory as the phpt test script. + +When creating temporary files it is a good idea to use an extension that indicates the use of the +file, eg .tmp. It's also a good idea to avoid using extensions that are already used for other +purposes, eg .inc, .php. Similarly, it is helpful to give the temporary file a name that is clearly +related to the test case. For example, mytest.phpt should create mytest.tmp (or mytestN.tmp, N=1, +2,3,...) then if by any chance the temporary file isnt't removed properly it will be obvious which +test case created it. + +When writing and debugging a test case with a --CLEAN-- section it is helpful to remember that the +php code in the --CLEAN-- section is executed separately from the code in the --FILE-- section. For +example, in a test case called mytest.phpt, code from the --FILE-- section is run from a file called +mytest.php and code from the --CLEAN-- section is run from a file called mytest.clean.php. If the +test passes, both the .php and .clean.php files are removed by ``run-tests.php``. You can prevent +the removal by using the --keep option of ``run-tests.php``, this is a very useful option if you +need to check that the --CLEAN-- section code is working as you intended. + +Finally — if you are using CVS it's helpful to add the extension that you use for test-related +temporary files to the .cvsignore file — this will help to prevent you from accidentally checking +temporary files into CVS. + +Redirecting tests +================= + +Using ``--REDIRECTTEST--`` it is possible to redirect from one test to a bunch of other tests. That +way multiple extensions can refer to the same set of test scripts probably using it with a different +configuration. + +The block is eval'd and supposed to return an array describing how to redirect. The resulting array +must contain the key 'TEST' that stores the redirect target as a string. This string usually is the +directory where the test scripts are located and should be relative. Optionally you can use the +'ENV' as an array configuring the environment to be set when executing the tests. This way you can +pass configuration to the executed tests. + +Redirect tests may especially contain ``--SKIPIF--``, ``--ENV--``, and ``--ARGS--`` sections but +they no not use any ``--EXPECT--`` section. + +The redirected tests themselves are just normal tests. + +Error reporting in tests +======================== + +All tests should run correctly with error_reporting(E_ALL) and display_errors=1. This is the default +when called from ``run-tests.php``. If you have a good reason for lowering the error reporting, use +``--INI--`` section and comment this in your testcode. + +If your test intentionally generates a PHP warning message use $php_errormsg variable, which you can +then output. This will result in a consistent error message output across all platforms and PHP +configurations, preventing your test from failing due inconsistencies in the error message content. +Alternatively you can use ``--EXPECTF--`` and check for the message by replacing the path of the +source of the message with "%s" and the line number with "%d". The end of a message in a test file +"example.phpt" then looks like "in %sexample.php on line %d". We explicitly dropped the last path +devider as that is a system dependent character '/' or '\'. + +Last bit +======== + +Often you want to run test scripts without ``run-tests.php`` by executing them on command line like +any other php script. But sometimes it disturbs having a long ``--EXPECT--`` block, so that you +don't see the actual output as it scrolls away overwritten by the blocks following the actual file +block. The workaround is to use terminate the ``--FILE--`` section with the two lines ``===DONE===`` +and ````. When doing so ``run-tests.php`` does not execute the line containing the +exit call as that would suppress leak messages. Actually ``run-tests.php`` ignores any part after a +line consisting only of ``===DONE===``. + +Here is an example: + +.. code:: php + + --TEST-- + Test hypot() — dealing with mixed number/character input + --INI-- + precision=14 + --FILE-- + + ===DONE=== + + --EXPECTF-- + 23abc :-33 float(40.224370722238) + ===DONE=== + +If executed as PHP script the output will stop after the code on the ``--FILE--`` section has been +run. + +*********** + Reference +*********** + +PHPT Sections +============= + +``--TEST--`` +------------ + +**Description:** Title of test as a single line short description. + +**Required:** Yes + +**Format:** Plain text. We recommend a single line only. + +Example 1 (snippet): + +.. code:: text + + --TEST-- + Test filter_input() with GET and POST data. + +Example 1 (full): sample001.phpt + +``--DESCRIPTION--`` +------------------- + +**Description:** If your test requires more than a single line title to adequately describe it, you +can use this section for further explanation. Multiple lines are allowed and besides being used for +information, this section is completely ignored by the test binary. + +**Required:** No + +**Format:** Plain text, multiple lines. + +Example 1 (snippet): + +.. code:: text + + --DESCRIPTION-- + This test covers both valid and invalid usages of filter_input() with INPUT_GET and INPUT_POST data and several differnet filter sanitizers. + +Example 1 (full): sample001.phpt + +``--CREDITS--`` +--------------- + +**Description:** Used to credit contributors without CVS commit rights, who put their name and email +on the first line. If the test was part of a TestFest event, then # followed by the name of the +event and the date (YYYY-MM-DD) on the second line. + +**Required:** No. For newly created tests this section should no longer be included, as test +authorship is already accurately tracked by Git. If multiple authors should be credited, the +`Co-authored-by` tag in the commit message may be used. + +**Format:** Name Email [Event] + +Example 1 (snippet): + +.. code:: text + + --CREDITS-- + Felipe Pena + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: text + + --CREDITS-- + Zoe Slattery zoe@php.net + # TestFest Munich 2009-05-19 + +Example 2 (full): sample002.phpt + +``--SKIPIF--`` +-------------- + +**Description:** A condition or set of conditions used to determine if a test should be skipped. +Tests that are only applicable to a certain platform, extension or PHP version are good reasons for +using a ``--SKIPIF--`` section. + +A common practice for extension tests is to write your ``--SKIPIF--`` extension criteria into a file +call skipif.inc and then including that file in the ``--SKIPIF--`` section of all your extension +tests. This promotes the DRY principle and reduces future code maintenance. + +**Required:** No. + +**Format:** PHP code enclosed by PHP tags. If the output of this scripts starts with "skip", the +test is skipped. If the output starts with "xfail", the test is marked as expected failure. If the +output starts with "flaky", the test is marked as flaky test. The "xfail" convention is supported as +of PHP 7.2.0. The "flaky" convention is supported as of PHP 8.2.25 and PHP 8.3.13, respectively. + +Example 1 (snippet): + +.. code:: php + + --SKIPIF-- + + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: php + + --SKIPIF-- + + +Example 2 (full): sample003.phpt + +Example 3 (snippet): + +.. code:: php + + --SKIPIF-- + + +Example 3 (full): xfailif.phpt + +Example 4 (snippet): + +.. code:: php + + --SKIPIF-- + string

&d=12345.7 + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: xml + + --POST-- + + + + + + +Example 2 (full): sample005.phpt + +``--POST_RAW--`` +---------------- + +**Description:** Raw POST data to be passed to the test script. This differs from the section above +because it doesn't automatically set the Content-Type, this leaves you free to define your own +within the section. This section forces the use of the CGI binary instead of the usual CLI one. + +**Required:** No. + +Requirements: PHP CGI binary. + +**Test Script Support:** ``run-tests.php`` + +**Format:** Follows the HTTP post data format. + +Example 1 (snippet): + +.. code:: text + + --POST_RAW-- + Content-type: multipart/form-data, boundary=AaB03x + + --AaB03x content-disposition: form-data; name="field1" + + Joe Blow + --AaB03x + content-disposition: form-data; name="pics"; filename="file1.txt" + Content-Type: text/plain + + abcdef123456789 + --AaB03x-- + +Example 1 (full): sample006.phpt + +``--PUT--`` +----------- + +**Description:** Similar to the section above, PUT data to be passed to the test script. This +section forces the use of the CGI binary instead of the usual CLI one. + +**Required:** No. + +Requirements: PHP CGI binary. + +**Test Script Support:** ``run-tests.php`` + +**Format:** Raw data optionally preceded by a Content-Type header. + +Example 1 (snippet): + +.. code:: text + + --PUT-- + Content-Type: text/json + + {"name":"default output handler","type":0,"flags":112,"level":0,"chunk_size":0,"buffer_size":16384,"buffer_used":3} + +``--GZIP_POST--`` +----------------- + +**Description:** When this section exists, the POST data will be gzencode()'d. This section forces +the use of the CGI binary instead of the usual CLI one. + +**Required:** No. + +**Test Script Support:** ``run-tests.php`` + +**Format:** Just add the content to be gzencode()'d in the section. + +Example 1 (snippet): + +.. code:: xml + + --GZIP_POST-- + + + + + + +Example 1 (full): sample005.phpt + +``--DEFLATE_POST--`` +-------------------- + +**Description:** When this section exists, the POST data will be gzcompress()'ed. This section +forces the use of the CGI binary instead of the usual CLI one. + +**Required:** No. + +Requirements: + +**Test Script Support:** ``run-tests.php`` + +**Format:** Just add the content to be gzcompress()'ed in the section. + +Example 1 (snippet): + +.. code:: xml + + --DEFLATE_POST-- + + + + + + + +Example 1 (full): sample007.phpt + +``--GET--`` +----------- + +**Description:** GET variables to be passed to the test script. This section forces the use of the +CGI binary instead of the usual CLI one. + +**Required:** No. + +Requirements: PHP CGI binary. + +**Format:** A single line of text passed as the GET data to the script. + +Example 1 (snippet): + +.. code:: text + + --GET-- + a=test&b=http://example.com + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: text + + --GET-- + ar[elm1]=1234&ar[elm2]=0660&a=0234 + +Example 2 (full): sample008.phpt + +``--COOKIE--`` +-------------- + +**Description:** Cookies to be passed to the test script. This section forces the use of the CGI +binary instead of the usual CLI one. + +**Required:** No. + +Requirements: PHP CGI binary. + +**Test Script Support:** ``run-tests.php`` + +**Format:** A single line of text in a valid HTTP cookie format. + +Example 1 (snippet): + +.. code:: + + --COOKIE-- + hello=World;goodbye=MrChips + +Example 1 (full): sample002.phpt + +``--STDIN--`` +------------- + +**Description:** Data to be fed to the test script's standard input. + +**Required:** No. + +**Test Script Support:** ``run-tests.php`` + +**Format:** Any text within this section is passed as STDIN to PHP. + +Example 1 (snippet): + +.. code:: text + + --STDIN-- + fooBar + use this to input some thing to the php script + +Example 1 (full): sample009.phpt + +``--INI--`` +----------- + +**Description:** To be used if you need a specific php.ini setting for the test. + +**Required:** No. + +**Format:** Key value pairs including automatically replaced tags. One setting per line. Content +that is not a valid ini setting may cause failures. + +The following is a list of all tags and what they are used to represent: + +- ``{PWD}``: Represents the directory of the file containing the ``--INI--`` section. +- ``{TMP}``: Represents the system's temporary directory. Available as of PHP 7.2.19 and 7.3.6. + +Example 1 (snippet): + +.. code:: text + + --INI-- + precision=14 + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: text + + --INI-- + session.use_cookies=0 + session.cache_limiter= + register_globals=1 + session.serialize_handler=php + session.save_handler=files + +Example 2 (full): sample003.phpt + +``--ARGS--`` +------------ + +**Description:** A single line defining the arguments passed to PHP. + +**Required:** No. + +**Format:** A single line of text that is passed as the argument(s) to the PHP CLI. + +Example 1 (snippet): + +.. code:: text + + --ARGS-- + --arg value --arg=value -avalue -a=value -a value + +Example 1 (full): sample010.phpt + +``--ENV--`` +----------- + +**Description:** Configures environment variables such as those found in the ``$_SERVER`` global +array. + +**Required:** No. + +**Format:** Key value pairs. One setting per line. + +Example 1 (snippet): + +.. code:: text + + --ENV-- + SCRIPT_NAME=/frontcontroller10.php + REQUEST_URI=/frontcontroller10.php/hi + PATH_INFO=/hi + +Example 1 (full): sample018.phpt + +``--PHPDBG--`` +-------------- + +**Description:** This section takes arbitrary phpdbg commands and executes the test file according +to them as it would be run in the phpdbg prompt. + +**Required:** No. + +**Format:** Arbitrary phpdbg commands + +Example 1 (snippet): + +.. code:: text + + --PHPDBG-- + b + 4 + b + del + 0 + b + 5 + r + b + del + 1 + r + y + q + +Example 1 (full): phpdbg_1.phpt + +``--FILE--`` +------------ + +**Description:** The test source code. + +**Required:** One of the ``FILE`` type sections is required. + +**Format:** PHP source code enclosed by PHP tags. + +Example 1 (snippet): + +.. code:: php + + --FILE-- + + +Example 1 (full): sample001.phpt + +``--FILEEOF--`` +--------------- + +**Description:** An alternative to ``--FILE--`` where any trailing line breaks (\n || \r || \r\n +found at the end of the section) are omitted. This is an extreme edge-case feature, so 99.99% of the +time you won't need this section. + +**Required:** One of the ``FILE`` type sections is required. + +**Test Script Support:** ``run-tests.php`` + +**Format:** PHP source code enclosed by PHP tags. + +Example 1 (snippet): + +.. code:: php + + --FILEEOF-- + array( + 'PDOTEST_DSN' => 'sqlite2::memory:' + ), + 'TESTS' => 'ext/pdo/tests' + ); + +Example 1 (full): sample013.phpt Note: The destination tests for this example are not included. See +the PDO extension tests for reference to live tests using this section. + +Example 2 (snippet): + +.. code:: php + + --REDIRECTTEST-- + # magic auto-configuration + + $config = array( + 'TESTS' => 'ext/pdo/tests' + ); + + if (false !== getenv('PDO_MYSQL_TEST_DSN')) { + # user set them from their shell + $config['ENV']['PDOTEST_DSN'] = getenv('PDO_MYSQL_TEST_DSN'); + $config['ENV']['PDOTEST_USER'] = getenv('PDO_MYSQL_TEST_USER'); + $config['ENV']['PDOTEST_PASS'] = getenv('PDO_MYSQL_TEST_PASS'); + if (false !== getenv('PDO_MYSQL_TEST_ATTR')) { + $config['ENV']['PDOTEST_ATTR'] = getenv('PDO_MYSQL_TEST_ATTR'); + } + } else { + $config['ENV']['PDOTEST_DSN'] = 'mysql:host=localhost;dbname=test'; + $config['ENV']['PDOTEST_USER'] = 'root'; + $config['ENV']['PDOTEST_PASS'] = ''; + } + + return $config; + +Example 2 (full): sample014.phpt + +Note: The destination tests for this example are not included. See the PDO extension tests for +reference to live tests using this section. + +``--CGI--`` +----------- + +**Description:** This section takes no value. It merely provides a simple marker for tests that MUST +be run as CGI, even if there is no ``--POST--`` or ``--GET--`` sections in the test file. + +**Required:** No. + +**Format:** No value, just the ``--CGI--`` statement. + +Example 1 (snippet): + +.. code:: text + + --CGI-- + +Example 1 (full): sample016.phpt + +``--XFAIL--`` +------------- + +**Description:** This section identifies this test as one that is currently expected to fail. It +should include a brief description of why it's expected to fail. Reasons for such expectations +include tests that are written before the functionality they are testing is implemented or notice of +a bug which is due to upstream code such as an extension which provides PHP support for some other +software. + +Please do NOT include an ``--XFAIL--`` without providing a text description for the reason it's +being used. + +**Required:** No. + +**Test Script Support:** ``run-tests.php`` + +**Format:** A short plain text description of why this test is currently expected to fail. + +Example 1 (snippet): + +.. code:: text + + --XFAIL-- + This bug might be still open on aix5.2-ppc64 and hpux11.23-ia64 + +Example 1 (full): sample017.phpt + +``--FLAKY--`` +------------- + +**Description:** This section identifies this test as one that occassionally fails. If the test +actually fails, it will be retried one more time, and that result will be reported. The section +should include a brief description of why the test is flaky. Reasons for this include tests that +rely on relatively precise timing, or temporary disc states. Available as of PHP 8.1.22 and 8.2.9, +respectively. + +Please do NOT include a ``--FLAKY--`` section without providing a text description for the reason it +is being used. + +**Required:** No. + +**Test Script Support:** ``run-tests.php`` + +**Format:** A short plain text description of why this test is flaky. + +Example 1 (snippet): + +.. code:: + + --FLAKY-- + This test frequently fails in CI + +Example 1 (full): flaky.phpt + +``--EXPECTHEADERS--`` +--------------------- + +**Description:** The expected headers. Any header specified here must exist in the response and have +the same value or the test fails. Additional headers found in the actual tests while running are +ignored. + +**Required:** No. + +**Format:** HTTP style headers. May include multiple lines. + +Example 1 (snippet): + +--EXPECTHEADERS-- Status: 404 + +Example 1 (snippet): + +.. code:: text + + --EXPECTHEADERS-- + Content-type: text/html; charset=UTF-8 + Status: 403 Access Denied + +Example 1 (full): sample018.phpt + +Note: The destination tests for this example are not included. See the phar extension tests for +reference to live tests using this section. + +``--EXPECT--`` +-------------- + +**Description:** The expected output from the test script. This must match the actual output from +the test script exactly for the test to pass. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Format:** Plain text. Multiple lines of text are allowed. + +Example 1 (snippet): + +.. code:: text + + --EXPECT-- + array(2) { + ["hello"]=> + string(5) "World" + ["goodbye"]=> + string(7) "MrChips" + } + +Example 1 (full): sample002.phpt + +``--EXPECT_EXTERNAL--`` +----------------------- + +**Description:** Similar to to ``--EXPECT--`` section, but just stating a filename where to load the +expected output from. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Test Script Support:** ``run-tests.php`` + +Example 1 (snippet): + +.. code:: text + + --EXPECT_EXTERNAL-- + test001.expected.txt + +*test001.expected.txt* + +.. code:: php + + array(2) { + ["hello"]=> + string(5) "World" + ["goodbye"]=> + string(7) "MrChips" + } + +``--EXPECTF--`` +--------------- + +**Description:** An alternative of ``--EXPECT--``. Where it differs from ``--EXPECT--`` is that it +uses a number of substitution tags for strings, spaces, digits, etc. that appear in test case output +but which may vary between test runs. The most common example of this is to use %s and %d to match +the file path and line number which are output by PHP Warnings. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Format:** Plain text including tags which are inserted to represent different types of output +which are not guaranteed to have the same value on subsequent runs or when run on different +platforms. + +The following is a list of all tags and what they are used to represent: + + - ``%e``: Represents a directory separator, for example / on Linux. + - ``%s``: One or more of anything (character or white space) except the end of line character. + - ``%S``: Zero or more of anything (character or white space) except the end of line character. + - ``%a``: One or more of anything (character or white space) including the end of line + character. + - ``%A``: Zero or more of anything (character or white space) including the end of line + character. + - ``%w``: Zero or more white space characters. + - ``%i``: A signed integer value, for example +3142, -3142, 3142. + - ``%d``: An unsigned integer value, for example 123456. + - ``%x``: One or more hexadecimal character. That is, characters in the range 0-9, a-f, A-F. + - ``%f``: A floating point number, for example: 3.142, -3.142, 3.142E-10, 3.142e+10. + - ``%c``: A single character of any sort (.). + - ``%r...%r``: Any string (...) enclosed between two ``%r`` will be treated as a regular + expression. + +Example 1 (snippet): + +.. code:: text + + --EXPECTF-- + string(4) "test" + string(18) "http://example.com/" + string(27) "<b>test</b>" + + Notice: Object of class stdClass could not be converted to int in %ssample001.php on line %d + bool(false) + string(6) "string" + float(12345.7) + string(29) "<p>string</p>" + bool(false) + + Warning: filter_var() expects parameter 2 to be long, string given in %s011.php on line %d + NULL + + Warning: filter_input() expects parameter 3 to be long, string given in %s011.php on line %d + NULL + + Warning: filter_var() expects at most 3 parameters, 5 given in %s011.php on line %d + NULL + + Warning: filter_var() expects at most 3 parameters, 5 given in %s011.php on line %d + NULL + Done + +Example 1 (full): sample001.phpt + +Example 2 (snippet): + +.. code:: text + + --EXPECTF-- + Warning: bzopen() expects exactly 2 parameters, 0 given in %s on line %d NULL + + Warning: bzopen(): '' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(): filename cannot be empty in %s on line %d + bool(false) + + Warning: bzopen(): filename cannot be empty in %s on line %d + bool(false) + + Warning: bzopen(): 'x' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(): 'rw' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(no_such_file): failed to open stream: No such file or directory in %s on line %d + bool(false) + resource(%d) of type (stream) Done + +Example 2 (full): sample019.phpt + +Example 3 (snippet): + +.. code:: text + + --EXPECTF-- + object(DOMNodeList)#%d (0) { + } + int(0) + bool(true) + bool(true) + string(0) "" + bool(true) + bool(true) + bool(false) + bool(false) + +Example 2 (full): sample020.phpt + +``--EXPECTF_EXTERNAL--`` +------------------------ + +**Description:** Similar to to ``--EXPECTF--`` section, but like the ``--EXPECT_EXTERNAL--`` section +just stating a filename where to load the expected output from. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Test Script Support:** ``run-tests.php`` + +``--EXPECTREGEX--`` +------------------- + +**Description:** An alternative of ``--EXPECT--``. This form allows the tester to specify the result +in a regular expression. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Format:** Plain text including regular expression patterns which represent data that can vary +between subsequent runs of a test or when run on different platforms. + +Example 1 (snippet): + +.. code:: text + + --EXPECTREGEX-- + M_E : 2.718281[0-9]* + M_LOG2E : 1.442695[0-9]* + M_LOG10E : 0.434294[0-9]* + M_LN2 : 0.693147[0-9]* + M_LN10 : 2.302585[0-9]* + M_PI : 3.141592[0-9]* + M_PI_2 : 1.570796[0-9]* + M_PI_4 : 0.785398[0-9]* + M_1_PI : 0.318309[0-9]* + M_2_PI : 0.636619[0-9]* + M_SQRTPI : 1.772453[0-9]* + M_2_SQRTPI: 1.128379[0-9]* + M_LNPI : 1.144729[0-9]* + M_EULER : 0.577215[0-9]* + M_SQRT2 : 1.414213[0-9]* + M_SQRT1_2 : 0.707106[0-9]* + M_SQRT3 : 1.732050[0-9]* + +Example 1 (full): sample021.phpt + +Example 2 (snippet): + +.. code:: text + + --EXPECTF-- + *** Testing imap_append() : basic functionality *** + Create a new mailbox for test + Create a temporary mailbox and add 0 msgs + .. mailbox '%s' created + Add a couple of msgs to new mailbox {%s}INBOX.%s + bool(true) + bool(true) + Msg Count after append : 2 + List the msg headers + array(2) { + [0]=> + string(%d) "%w%s 1)%s webmaster@something. Test message (%d chars)" + [1]=> + string(%d) "%w%s 2)%s webmaster@something. Another test (%d chars)" + } + +Example 2 (full): sample025.phpt + +Example 3 (snippet): + +.. code:: text + + --EXPECTREGEX-- + string\(4\) \"-012\" + string\(8\) \"2d303132\" + (string\(13\) \" 4294967284\"|string\(20\) \"18446744073709551604\") + (string\(26\) \"20202034323934393637323834\"|string\(40\) \"3138343436373434303733373039353531363034\") + + Example 3 (full): sample023.phpt + +``--EXPECTREGEX_EXTERNAL--`` +---------------------------- + +**Description:** Similar to to ``--EXPECTREGEX--`` section, but like the ``--EXPECT_EXTERNAL--`` +section just stating a filename where to load the expected output from. + +**Required:** One of the ``EXPECT`` type sections is required. + +**Test Script Support:** ``run-tests.php`` + +``--CLEAN--`` +------------- + +**Description:** Code that is executed after a test completes. It's main purpose is to allow you to +clean up after yourself. You might need to remove files created during the test or close sockets or +database connections following a test. Infact, even if a test fails or encounters a fatal error +during the test, the code found in the ``--CLEAN--`` section will still run. + +Code in the clean section is run in a completely different process than the one the test was run in. +So do not try accessing variables you created in the ``--FILE--`` section from inside the +``--CLEAN--`` section, they won't exist. + +Using the switch ``--no-clean`` on ``run-tests.php``, you can prevent the code found in the +``--CLEAN--`` section of a test from running. This allows you to inspect generated data or files +without them being removed by the ``--CLEAN--`` section. + +**Required:** No. + +**Test Script Support:** ``run-tests.php`` + +**Format:** PHP source code enclosed by PHP tags. + +Example 1 (snippet): + +.. code:: php + + --CLEAN-- + + +Example 1 (full): sample024.phpt + +Example 2 (snippet): + +.. code:: php + + --CLEAN-- + + +Example 2 (full): sample025.phpt + +Example 3 (snippet): + +.. code:: php + + --CLEAN-- + + +Example 3 (full): sample022.phpt + +Samples +======= From eb048ce0c6250f8a75b4ebb45f9b3398d415cf18 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 23 Apr 2025 17:29:16 +0100 Subject: [PATCH 404/503] Add samples from original QA site --- docs/source/conf.py | 1 + docs/source/index.rst | 1 + docs/source/miscellaneous/writing-tests.rst | 1375 +++++++++++++++++-- 3 files changed, 1287 insertions(+), 90 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 1129eb08a8216..7347682eddf48 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,6 +16,7 @@ author = 'The PHP Group' extensions = [ 'sphinx_design', + 'sphinx.ext.autosectionlabel', ] templates_path = ['_templates'] html_theme = 'sphinxawesome_theme' diff --git a/docs/source/index.rst b/docs/source/index.rst index 53178820892a6..5d81398edef26 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -20,6 +20,7 @@ :hidden: miscellaneous/stubs + miscellaneous/writing-tests Welcome to the php-src documentation! diff --git a/docs/source/miscellaneous/writing-tests.rst b/docs/source/miscellaneous/writing-tests.rst index e16e905beda93..8b5445cf4193a 100644 --- a/docs/source/miscellaneous/writing-tests.rst +++ b/docs/source/miscellaneous/writing-tests.rst @@ -190,21 +190,22 @@ other platforms. If you don't have karma to commit have a look at the next secti When you are testing your test case it's really important to make sure that you clean up any temporary resources (eg files) that you used in the test. There is a special ``--CLEAN--`` section -to help you do this — see here. +to help you do this — see `here <#clean>`_. Another good check is to look at what lines of code in the PHP source your test case covers. This is -easy to do, there are some instructions on the PHP Wiki. +easy to do, there are some instructions on the `PHP Wiki +`_. What should I do with my test case when I've written and tested it? =================================================================== The next step is to get someone to review it. If it's short you can paste it into a note and send it to php-qa@lists.php.net. If the test is a bit too long for that then put it somewhere were people -can download it (pastebin is sometimes used). Appending tests to notes as files doesn't work well - -so please don't do that. Your note to php-qa@lists.php.net should say what level of PHP you have -tested it on and what platform(s) you've run it on. Someone from the PHP QA group will review your -test and reply to you. They may ask for some changes or suggest better ways to do things, or they -may commit it to PHP. +can download it (`pastebin `_ is sometimes used). Appending tests to notes as +files doesn't work well - so please don't do that. Your note to php-qa@lists.php.net should say what +level of PHP you have tested it on and what platform(s) you've run it on. Someone from the PHP QA +group will review your test and reply to you. They may ask for some changes or suggest better ways +to do things, or they may commit it to PHP. Writing Portable PHP Tests ========================== @@ -218,11 +219,11 @@ that environment. Make sure sets of data are consistently ordered. SQL queries are not guaranteed to return results in the same order unless an ORDER BY clause is used. Directory listings are another example that can -vary: use an appropriate PHP function to sort them befor printing. Both of these examples have +vary: use an appropriate PHP function to sort them before printing. Both of these examples have affected PHP tests in the past. -Make sure that any test touching parsing or display of dates uses a hard-defined timezone - -preferable 'UTC'. It is important tha this is defined in the file section using: +Make sure that any test touching parsing or display of dates uses a hard-defined timezone — +preferable 'UTC'. It is important that this is defined in the file section using: .. code:: php @@ -289,15 +290,16 @@ To skip a test on Mac OS X Darwin: EXPECTF ======= -/ext/standard/tests/strings/str_shuffle.phpt is a good example for using EXPECTF instead of EXPECT. -From time to time the algorithm used for shuffle changed and sometimes the machine used to execute -the code has influence on the result of shuffle. But it always returns a three character string -detectable by %s (that matches any string until the end of the line). Other scan-able forms are %a -for any amount of chars (at least one), %i for integers, %d for numbers only, %f for floating point -values, %c for single characters, %x for hexadecimal values, %w for any number of whitespace -characters and %e for DIRECTORY_SEPARATOR ('\' or '/'). +``/ext/standard/tests/strings/str_shuffle.phpt`` is a good example for using ``EXPECTF`` instead of +``EXPECT``. From time to time the algorithm used for shuffle changed and sometimes the machine used +to execute the code has influence on the result of shuffle. But it always returns a three character +string detectable by ``%s`` (that matches any string until the end of the line). Other scan-able +forms are ``%a`` for any amount of chars (at least one), ``%i`` for integers, ``%d`` for numbers +only, ``%f`` for floating point values, ``%c`` for single characters, ``%x`` for hexadecimal values, +``%w`` for any number of whitespace characters and ``%e`` for ``DIRECTORY_SEPARATOR`` (``'\'`` or +``'/'``). -See also EXPECTF details +See also `EXPECTF <#expectf>`_ details. */ext/standard/tests/strings/str_shuffle.phpt* @@ -319,9 +321,9 @@ See also EXPECTF details EXPECTREGEX =========== -/ext/standard/tests/strings/strings001.phpt is a good example for using EXPECTREGEX instead of -EXPECT. This test also shows that in EXPECTREGEX some characters need to be escaped since otherwise -they would be interpreted as a regular expression. +``/ext/standard/tests/strings/strings001.phpt`` is a good example for using ``EXPECTREGEX`` instead +of ``EXPECT``. This test also shows that in ``EXPECTREGEX`` some characters need to be escaped since +otherwise they would be interpreted as a regular expression. */ext/standard/tests/strings/strings001.phpt* @@ -344,8 +346,8 @@ EXTENSIONS ========== Some tests depend on PHP extensions that may be unavailable. These extensions should be listed in -the EXTENSIONS section. If an extension is missing, PHP will try to find it in a shared module and -skip the test if it's not there. +the ``EXTENSIONS`` section. If an extension is missing, PHP will try to find it in a shared module +and skip the test if it's not there. */ext/sodium/tests/crypto_scalarmult.phpt* @@ -364,9 +366,9 @@ SKIPIF Some tests depend on modules or functions available only in certain versions or they even require minimum version of php or zend. These tests should be skipped when the requirement cannot be -fulfilled. To achieve this you can use the SKIPIF section. To tell ``run-tests.php`` that your test -should be skipped the SKIPIF section must print out the word "skip" followed by a reason why the -test should skip. +fulfilled. To achieve this you can use the ``SKIPIF`` section. To tell ``run-tests.php`` that your +test should be skipped the ``SKIPIF`` section must print out the word "skip" followed by a reason +why the test should skip. *ext/sodium/tests/pwhash_argon2i.phpt* @@ -383,13 +385,14 @@ test should skip. --FILE-- [snip] -Test script and SKIPIF code should be directly written into \*.phpt. However, it is recommended to -use include files when more test scripts depend on the same SKIPIF code or when certain test files -need the same values for some input. +Test script and ``SKIPIF`` code should be directly written into ``\*.phpt``. However, it is +recommended to use include files when more test scripts depend on the same ``SKIPIF`` code or when +certain test files need the same values for some input. Note: no file used by any test should have one of the following extensions: ".php", ".log", ".mem", -".exp", ".out" or ".diff". When you use an include file for the SKIPIF section it should be named -"skipif.inc" and an include file used in the FILE section of many tests should be named "test.inc". +".exp", ".out" or ".diff". When you use an include file for the ``SKIPIF`` section it should be +named "skipif.inc" and an include file used in the ``FILE`` section of many tests should be named +"test.inc". ************* Final Notes @@ -444,8 +447,8 @@ Here is a better way to write the code: ?> --EXPECT-- -Note the use of the __DIR__ construct which will ensure that the temporary file is created in the -same directory as the phpt test script. +Note the use of the ``__DIR__`` construct which will ensure that the temporary file is created in +the same directory as the phpt test script. When creating temporary files it is a good idea to use an extension that indicates the use of the file, eg .tmp. It's also a good idea to avoid using extensions that are already used for other @@ -454,13 +457,14 @@ related to the test case. For example, mytest.phpt should create mytest.tmp (or 2,3,...) then if by any chance the temporary file isnt't removed properly it will be obvious which test case created it. -When writing and debugging a test case with a --CLEAN-- section it is helpful to remember that the -php code in the --CLEAN-- section is executed separately from the code in the --FILE-- section. For -example, in a test case called mytest.phpt, code from the --FILE-- section is run from a file called -mytest.php and code from the --CLEAN-- section is run from a file called mytest.clean.php. If the -test passes, both the .php and .clean.php files are removed by ``run-tests.php``. You can prevent -the removal by using the --keep option of ``run-tests.php``, this is a very useful option if you -need to check that the --CLEAN-- section code is working as you intended. +When writing and debugging a test case with a ``--CLEAN--`` section it is helpful to remember that +the php code in the ``--CLEAN--`` section is executed separately from the code in the ``--FILE--`` +section. For example, in a test case called mytest.phpt, code from the ``--FILE--`` section is run +from a file called mytest.php and code from the ``--CLEAN--`` section is run from a file called +mytest.clean.php. If the test passes, both the .php and .clean.php files are removed by +``run-tests.php``. You can prevent the removal by using the --keep option of ``run-tests.php``, this +is a very useful option if you need to check that the ``--CLEAN--`` section code is working as you +intended. Finally — if you are using CVS it's helpful to add the extension that you use for test-related temporary files to the .cvsignore file — this will help to prevent you from accidentally checking @@ -495,9 +499,9 @@ If your test intentionally generates a PHP warning message use $php_errormsg var then output. This will result in a consistent error message output across all platforms and PHP configurations, preventing your test from failing due inconsistencies in the error message content. Alternatively you can use ``--EXPECTF--`` and check for the message by replacing the path of the -source of the message with "%s" and the line number with "%d". The end of a message in a test file -"example.phpt" then looks like "in %sexample.php on line %d". We explicitly dropped the last path -devider as that is a system dependent character '/' or '\'. +source of the message with ``%s`` and the line number with ``%d``. The end of a message in a test +file ``example.phpt`` then looks like ``in %sexample.php on line %d``. We explicitly dropped the +last path devider as that is a system dependent character ``/`` or ``\``. Last bit ======== @@ -558,7 +562,7 @@ Example 1 (snippet): --TEST-- Test filter_input() with GET and POST data. -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` ``--DESCRIPTION--`` ------------------- @@ -578,7 +582,7 @@ Example 1 (snippet): --DESCRIPTION-- This test covers both valid and invalid usages of filter_input() with INPUT_GET and INPUT_POST data and several differnet filter sanitizers. -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` ``--CREDITS--`` --------------- @@ -600,7 +604,7 @@ Example 1 (snippet): --CREDITS-- Felipe Pena -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -610,7 +614,7 @@ Example 2 (snippet): Zoe Slattery zoe@php.net # TestFest Munich 2009-05-19 -Example 2 (full): sample002.phpt +Example 2 (full): :ref:`sample002.phpt` ``--SKIPIF--`` -------------- @@ -637,7 +641,7 @@ Example 1 (snippet): --SKIPIF-- -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -646,7 +650,7 @@ Example 2 (snippet): --SKIPIF-- -Example 2 (full): sample003.phpt +Example 2 (full): :ref:`sample003.phpt` Example 3 (snippet): @@ -655,7 +659,7 @@ Example 3 (snippet): --SKIPIF-- -Example 3 (full): xfailif.phpt +Example 3 (full): :ref:`xfailif.phpt` Example 4 (snippet): @@ -667,8 +671,6 @@ Example 4 (snippet): die("flaky Occasionally segfaults on macOS for unknown reasons"); } -Example 4 (full): flakyif.phpt - ``--CONFLICTS--`` ----------------- @@ -692,7 +694,7 @@ Example 1 (snippet): --CONFLICTS-- server -Example 1 (full): conflicts_1.phpt +Example 1 (full): :ref:`conflicts_1.phpt` ``--WHITESPACE_SENSITIVE--`` ---------------------------- @@ -728,7 +730,7 @@ Example 1 (snippet): --CAPTURE_STDIO-- STDIN STDERR -Example 1 (full): capture_stdio_1.phpt +Example 1 (full): :ref:`capture_stdio_1.phpt` Example 2 (snippet): @@ -737,7 +739,7 @@ Example 2 (snippet): --CAPTURE_STDIO-- STDIN STDOUT -Example 2 (full): capture_stdio_2.phpt +Example 2 (full): :ref:`capture_stdio_2.phpt` Example 3 (snippet): @@ -746,7 +748,7 @@ Example 3 (snippet): --CAPTURE_STDIO-- STDIN STDOUT STDERR -Example 3(full): capture_stdio_3.phpt +Example 3(full): :ref:`capture_stdio_3.phpt` ``--EXTENSIONS--`` ------------------ @@ -769,7 +771,7 @@ Example 1 (snippet): imagick tokenizer -Example 1 (full): extensions.phpt +Example 1 (full): :ref:`extensions.phpt` ``--POST--`` ------------ @@ -790,7 +792,7 @@ Example 1 (snippet): --POST-- c=

string

&d=12345.7 -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -808,7 +810,7 @@ Example 2 (snippet): -Example 2 (full): sample005.phpt +Example 2 (full): :ref:`sample005.phpt` ``--POST_RAW--`` ---------------- @@ -842,7 +844,7 @@ Example 1 (snippet): abcdef123456789 --AaB03x-- -Example 1 (full): sample006.phpt +Example 1 (full): :ref:`sample006.phpt` ``--PUT--`` ----------- @@ -895,7 +897,7 @@ Example 1 (snippet): -Example 1 (full): sample005.phpt +Example 1 (full): :ref:`sample005.phpt` ``--DEFLATE_POST--`` -------------------- @@ -928,7 +930,7 @@ Example 1 (snippet): -Example 1 (full): sample007.phpt +Example 1 (full): :ref:`sample007.phpt` ``--GET--`` ----------- @@ -949,7 +951,7 @@ Example 1 (snippet): --GET-- a=test&b=http://example.com -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -958,7 +960,7 @@ Example 2 (snippet): --GET-- ar[elm1]=1234&ar[elm2]=0660&a=0234 -Example 2 (full): sample008.phpt +Example 2 (full): :ref:`sample008.phpt` ``--COOKIE--`` -------------- @@ -981,7 +983,7 @@ Example 1 (snippet): --COOKIE-- hello=World;goodbye=MrChips -Example 1 (full): sample002.phpt +Example 1 (full): :ref:`sample002.phpt` ``--STDIN--`` ------------- @@ -1002,7 +1004,7 @@ Example 1 (snippet): fooBar use this to input some thing to the php script -Example 1 (full): sample009.phpt +Example 1 (full): :ref:`sample009.phpt` ``--INI--`` ----------- @@ -1026,7 +1028,7 @@ Example 1 (snippet): --INI-- precision=14 -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -1039,7 +1041,7 @@ Example 2 (snippet): session.serialize_handler=php session.save_handler=files -Example 2 (full): sample003.phpt +Example 2 (full): :ref:`sample003.phpt` ``--ARGS--`` ------------ @@ -1057,7 +1059,7 @@ Example 1 (snippet): --ARGS-- --arg value --arg=value -avalue -a=value -a value -Example 1 (full): sample010.phpt +Example 1 (full): :ref:`sample010.phpt` ``--ENV--`` ----------- @@ -1078,7 +1080,7 @@ Example 1 (snippet): REQUEST_URI=/frontcontroller10.php/hi PATH_INFO=/hi -Example 1 (full): sample018.phpt +Example 1 (full): :ref:`sample018.phpt` ``--PHPDBG--`` -------------- @@ -1110,7 +1112,7 @@ Example 1 (snippet): y q -Example 1 (full): phpdbg_1.phpt +Example 1 (full): :ref:`phpdbg_1.phpt` ``--FILE--`` ------------ @@ -1143,7 +1145,7 @@ Example 1 (snippet): echo "Done\n"; ?> -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` ``--FILEEOF--`` --------------- @@ -1168,7 +1170,7 @@ Example 1 (snippet): echo " World"; //last line comment -Example 1 (full): sample011.phpt +Example 1 (full): :ref:`sample011.phpt` ``--FILE_EXTERNAL--`` --------------------- @@ -1192,7 +1194,7 @@ Example 1 (snippet): --FILE_EXTERNAL-- files/file012.inc -Example 1 (full): sample012.phpt +Example 1 (full): :ref:`sample012.phpt` ``--REDIRECTTEST--`` -------------------- @@ -1225,8 +1227,8 @@ Example 1 (snippet): 'TESTS' => 'ext/pdo/tests' ); -Example 1 (full): sample013.phpt Note: The destination tests for this example are not included. See -the PDO extension tests for reference to live tests using this section. +Example 1 (full): :ref:`sample013.phpt` Note: The destination tests for this example are not +included. See the PDO extension tests for reference to live tests using this section. Example 2 (snippet): @@ -1255,7 +1257,7 @@ Example 2 (snippet): return $config; -Example 2 (full): sample014.phpt +Example 2 (full): :ref:`sample014.phpt` Note: The destination tests for this example are not included. See the PDO extension tests for reference to live tests using this section. @@ -1276,7 +1278,7 @@ Example 1 (snippet): --CGI-- -Example 1 (full): sample016.phpt +Example 1 (full): :ref:`sample016.phpt` ``--XFAIL--`` ------------- @@ -1303,7 +1305,7 @@ Example 1 (snippet): --XFAIL-- This bug might be still open on aix5.2-ppc64 and hpux11.23-ia64 -Example 1 (full): sample017.phpt +Example 1 (full): :ref:`sample017.phpt` ``--FLAKY--`` ------------- @@ -1355,7 +1357,7 @@ Example 1 (snippet): Content-type: text/html; charset=UTF-8 Status: 403 Access Denied -Example 1 (full): sample018.phpt +Example 1 (full): :ref:`sample018.phpt` Note: The destination tests for this example are not included. See the phar extension tests for reference to live tests using this section. @@ -1382,7 +1384,7 @@ Example 1 (snippet): string(7) "MrChips" } -Example 1 (full): sample002.phpt +Example 1 (full): :ref:`sample002.phpt` ``--EXPECT_EXTERNAL--`` ----------------------- @@ -1473,7 +1475,7 @@ Example 1 (snippet): NULL Done -Example 1 (full): sample001.phpt +Example 1 (full): :ref:`sample001.phpt` Example 2 (snippet): @@ -1501,7 +1503,7 @@ Example 2 (snippet): bool(false) resource(%d) of type (stream) Done -Example 2 (full): sample019.phpt +Example 2 (full): :ref:`sample019.phpt` Example 3 (snippet): @@ -1519,7 +1521,7 @@ Example 3 (snippet): bool(false) bool(false) -Example 2 (full): sample020.phpt +Example 2 (full): :ref:`sample020.phpt` ``--EXPECTF_EXTERNAL--`` ------------------------ @@ -1565,7 +1567,7 @@ Example 1 (snippet): M_SQRT1_2 : 0.707106[0-9]* M_SQRT3 : 1.732050[0-9]* -Example 1 (full): sample021.phpt +Example 1 (full): :ref:`sample021.phpt` Example 2 (snippet): @@ -1588,7 +1590,7 @@ Example 2 (snippet): string(%d) "%w%s 2)%s webmaster@something. Another test (%d chars)" } -Example 2 (full): sample025.phpt +Example 2 (full): :ref:`sample025.phpt` Example 3 (snippet): @@ -1600,7 +1602,7 @@ Example 3 (snippet): (string\(13\) \" 4294967284\"|string\(20\) \"18446744073709551604\") (string\(26\) \"20202034323934393637323834\"|string\(40\) \"3138343436373434303733373039353531363034\") - Example 3 (full): sample023.phpt + Example 3 (full): :ref:`sample023.phpt` ``--EXPECTREGEX_EXTERNAL--`` ---------------------------- @@ -1643,7 +1645,7 @@ Example 1 (snippet): unlink(__DIR__.'/DomDocument_save_basic.tmp'); ?> -Example 1 (full): sample024.phpt +Example 1 (full): :ref:`sample024.phpt` Example 2 (snippet): @@ -1654,7 +1656,7 @@ Example 2 (snippet): require_once('clean.inc'); ?> -Example 2 (full): sample025.phpt +Example 2 (full): :ref:`sample025.phpt` Example 3 (snippet): @@ -1667,7 +1669,1200 @@ Example 3 (snippet): shm_remove($s); ?> -Example 3 (full): sample022.phpt +Example 3 (full): :ref:`sample022.phpt` Samples ======= + +capture_stdio_1.phpt +-------------------- + +.. code:: php + + --TEST-- + Test covering the I/O stdin and stdout streams. + --DESCRIPTION-- + This tests checks if the output of stdin and stdout I/O streams match the + expected content. + --CAPTURE_STDIO-- + STDIN STDERR + --FILE-- + + --EXPECT-- + This is error sent to the stderr I/O stream + +capture_stdio_2.phpt +-------------------- + +.. code:: php + + --TEST-- + Test covering the I/O stdin and stderr streams. + --DESCRIPTION-- + This tests checks if the output of stdin and stderr I/O streams match the + expected content. + --CAPTURE_STDIO-- + STDIN STDOUT + --FILE-- + + --EXPECT-- + Hello, world. This is sent to the stdout I/O stream + +capture_stdio_3.phpt +-------------------- + +.. code:: php + + --TEST-- + Test covering the all standard I/O streams. + --DESCRIPTION-- + This tests checks if the output of stdin, stdout and stderr I/O streams match + the expected content. + --CAPTURE_STDIO-- + STDIN STDOUT STDERR + --FILE-- + + --EXPECT-- + Hello, world. This is sent to the stdout I/O stream + This is error sent to the stderr I/O stream + +clean.php +--------- + +.. code:: php + + Nmsgs; $i++) { + imap_delete($imap_stream, $i); + } + + $mailboxes = imap_getmailboxes($imap_stream, $server, '*'); + + foreach($mailboxes as $value) { + // Only delete mailboxes with our prefix + if (preg_match('/\{.*?\}INBOX\.(.+)/', $value->name, $match) == 1) { + if (strlen($match[1]) >= strlen($mailbox_prefix) + && substr_compare($match[1], $mailbox_prefix, 0, strlen($mailbox_prefix)) == 0) { + imap_deletemailbox($imap_stream, $value->name); + } + } + } + + imap_close($imap_stream, CL_EXPUNGE); + ?> + +conflicts_1.phpt +---------------- + +.. code:: php + + --TEST-- + Test get_headers() function : test with context + --CONFLICTS-- + server + --FILE-- + array( + 'method' => 'HEAD' + ) + ); + + $context = stream_context_create($opts); + $headers = get_headers("http://".PHP_CLI_SERVER_ADDRESS, 1, $context); + echo $headers["X-Request-Method"]."\n"; + + stream_context_set_default($opts); + $headers = get_headers("http://".PHP_CLI_SERVER_ADDRESS, 1); + echo $headers["X-Request-Method"]."\n"; + + echo "Done"; + ?> + --EXPECT-- + HEAD + HEAD + Done + +extensions.phpt +--------------- + +.. code:: php + + --TEST-- + phpt EXTENSIONS directive with shared extensions + --DESCRIPTION-- + This test covers the presence of some loaded extensions with a list of additional + extensions to be loaded when running test. + --EXTENSIONS-- + curl + imagick + tokenizer + --FILE-- + + --EXPECT-- + bool(true) + bool(true) + bool(true) + +file012.phpt +------------ + +.. code:: php + + + +phpdbg_1.phpt +------------- + +.. code:: php + + --TEST-- + Test deleting breakpoints + --PHPDBG-- + b 4 + b del 0 + b 5 + r + b del 1 + r + y + q + --EXPECTF-- + [Successful compilation of %s] + prompt> [Breakpoint #0 added at %s:4] + prompt> [Deleted breakpoint #0] + prompt> [Breakpoint #1 added at %s:5] + prompt> 12 + [Breakpoint #1 at %s:5, hits: 1] + >00005: echo $i++; + 00006: echo $i++; + 00007: + prompt> [Deleted breakpoint #1] + prompt> Do you really want to restart execution? (type y or n): 1234 + [Script ended normally] + prompt> + --FILE-- + + --INI-- + precision=14 + --SKIPIF-- + + --GET-- + a=test&b=https://example.com + --POST-- + c=

string

&d=12345.7 + --FILE-- + + --EXPECTF-- + string(4) "test" + string(19) "https://example.com/" + string(27) "<b>test</b>" + + Notice: Object of class stdClass could not be converted to int in %ssample001.php on line %d + bool(false) + string(6) "string" + float(12345.7) + string(29) "<p>string</p>" + bool(false) + + Warning: filter_var() expects parameter 2 to be long, string given in %ssample001.php on line %d + NULL + + Warning: filter_input() expects parameter 3 to be long, string given in %ssample001.php on line %d + NULL + + Warning: filter_var() expects at most 3 parameters, 5 given in %ssample001.php on line %d + NULL + + Warning: filter_var() expects at most 3 parameters, 5 given in %ssample001.php on line %d + NULL + Done + +sample002.phpt +-------------- + +.. code:: php + + --TEST-- + Test receipt of cookie data. + --CREDITS-- + Zoe Slattery zoe@php.net + # TestFest Munich 2009-05-19 + --COOKIE-- + hello=World;goodbye=MrChips + --FILE-- + + --EXPECT-- + array(2) { + ["hello"]=> + string(5) "World" + ["goodbye"]=> + string(7) "MrChips" + } + +sample003.phpt +-------------- + +.. code:: php + + --TEST-- + session object deserialization + --SKIPIF-- + + --INI-- + session.use_cookies=0 + session.cache_limiter= + register_globals=1 + session.serialize_handler=php + session.save_handler=files + --FILE-- + yes++; } + } + + session_id("abtest"); + session_start(); + session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'); + + $baz->method(); + $arr[3]->method(); + + var_dump($baz); + var_dump($arr); + session_destroy(); + --EXPECT-- + object(foo)#1 (2) { + ["bar"]=> + string(2) "ok" + ["yes"]=> + int(2) + } + array(1) { + [3]=> + object(foo)#2 (2) { + ["bar"]=> + string(2) "ok" + ["yes"]=> + int(2) + } + } + +sample005.phpt +-------------- + +.. code:: php + + --TEST-- + SOAP Server 19: compressed request (gzip) + --SKIPIF-- + + --INI-- + precision=14 + --GZIP_POST-- + + + + + + --FILE-- + "http://testuri.org/")); + $server->addfunction("test"); + $server->handle(); + echo "ok\n"; + ?> + --EXPECT-- + + Hello World + ok + +sample006.phpt +-------------- + +.. code:: php + + --TEST-- + is_uploaded_file() function + --CREDITS-- + Dave Kelsey + --SKIPIF-- + + --POST_RAW-- + Content-type: multipart/form-data, boundary=AaB03x + + --AaB03x + content-disposition: form-data; name="field1" + + Joe Blow + --AaB03x + content-disposition: form-data; name="pics"; filename="file1.txt" + Content-Type: text/plain + + abcdef123456789 + --AaB03x-- + --FILE-- + + --EXPECTF-- + bool(true) + bool(false) + bool(false) + bool(false) + + Warning: is_uploaded_file() expects exactly 1 parameter, 0 given in %s on line %d + NULL + + Warning: is_uploaded_file() expects exactly 1 parameter, 2 given in %s on line %d + NULL + +sample007.phpt +-------------- + +.. code:: php + + --TEST-- + SOAP Server 20: compressed request (deflate) + --SKIPIF-- + + --INI-- + precision=14 + --DEFLATE_POST-- + + + + + + + --FILE-- + "http://testuri.org/")); + $server->addfunction("test"); + $server->handle(); + echo "ok\n"; + ?> + --EXPECT-- + + Hello World + ok + +sample008.phpt +-------------- + +.. code:: php + + --TEST-- + GET/POST/REQUEST Test with input_filter + --SKIPIF-- + + --POST-- + d=379 + --GET-- + ar[elm1]=1234&ar[elm2]=0660&a=0234 + --FILE-- + FILTER_FLAG_ALLOW_OCTAL)); + var_dump($ret); + + $ret = filter_input(INPUT_GET, 'ar', FILTER_VALIDATE_INT, array('flags'=>FILTER_REQUIRE_ARRAY)); + var_dump($ret); + + $ret = filter_input(INPUT_GET, 'ar', FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_REQUIRE_ARRAY)); + var_dump($ret); + + ?> + --EXPECT-- + bool(false) + int(156) + array(2) { + ["elm1"]=> + int(1234) + ["elm2"]=> + bool(false) + } + array(2) { + ["elm1"]=> + int(1234) + ["elm2"]=> + int(432) + } + +sample009.phpt +-------------- + +.. code:: php + + --TEST-- + STDIN input + --FILE-- + + --STDIN-- + fooBar + use this to input some thing to the php script + --EXPECT-- + string(54) "fooBar + use this to input some thing to the php script + " + +sample010.phpt +-------------- + +.. code:: php + + --TEST-- + getopt#005 (Required values) + --ARGS-- + --arg value --arg=value -avalue -a=value -a value + --INI-- + register_argc_argv=On + variables_order=GPS + --FILE-- + + --EXPECT-- + array(2) { + ["arg"]=> + array(2) { + [0]=> + string(5) "value" + [1]=> + string(5) "value" + } + ["a"]=> + array(3) { + [0]=> + string(5) "value" + [1]=> + string(5) "value" + [2]=> + string(5) "value" + } + } + +sample011.phpt +-------------- + +.. code:: php + + --TEST-- + Bug #35382 (Comment in end of file produces fatal error) + --FILEEOF-- + + --REDIRECTTEST-- + return array( + 'ENV' => array( + 'PDOTEST_DSN' => 'sqlite2::memory:' + ), + 'TESTS' => 'ext/pdo/tests' + ); + +sample014.phpt +-------------- + +.. code:: php + + --TEST-- + MySQL + --SKIPIF-- + + --REDIRECTTEST-- + # magic auto-configuration + + $config = array( + 'TESTS' => 'ext/pdo/tests' + ); + + if (false !== getenv('PDO_MYSQL_TEST_DSN')) { + # user set them from their shell + $config['ENV']['PDOTEST_DSN'] = getenv('PDO_MYSQL_TEST_DSN'); + $config['ENV']['PDOTEST_USER'] = getenv('PDO_MYSQL_TEST_USER'); + $config['ENV']['PDOTEST_PASS'] = getenv('PDO_MYSQL_TEST_PASS'); + if (false !== getenv('PDO_MYSQL_TEST_ATTR')) { + $config['ENV']['PDOTEST_ATTR'] = getenv('PDO_MYSQL_TEST_ATTR'); + } + } else { + $config['ENV']['PDOTEST_DSN'] = 'mysql:host=localhost;dbname=test'; + $config['ENV']['PDOTEST_USER'] = 'root'; + $config['ENV']['PDOTEST_PASS'] = ''; + } + + return $config; + +sample016.phpt +-------------- + +.. code:: php + + --TEST-- + Test get variables with CGI binary + --GET-- + hello=World&goodbye=MrChips + --CGI-- + --FILE-- + + --EXPECT-- + array(2) { + ["hello"]=> + string(5) "World" + ["goodbye"]=> + string(7) "MrChips" + } + +sample017.phpt +-------------- + +.. code:: php + + --TEST-- + PDO Common: Bug #34630 (inserting streams as LOBs) + --SKIPIF-- + + --FILE-- + getAttribute(PDO::ATTR_DRIVER_NAME); + $is_oci = $driver == 'oci'; + + if ($is_oci) { + $db->exec('CREATE TABLE test (id int NOT NULL PRIMARY KEY, val BLOB)'); + } else { + $db->exec('CREATE TABLE test (id int NOT NULL PRIMARY KEY, val VARCHAR(256))'); + } + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $fp = tmpfile(); + fwrite($fp, "I am the LOB data"); + rewind($fp); + + if ($is_oci) { + /* oracle is a bit different; you need to initiate a transaction otherwise + * the empty blob will be committed implicitly when the statement is + * executed */ + $db->beginTransaction(); + $insert = $db->prepare("insert into test (id, val) values (1, EMPTY_BLOB()) RETURNING val INTO :blob"); + } else { + $insert = $db->prepare("insert into test (id, val) values (1, :blob)"); + } + $insert->bindValue(':blob', $fp, PDO::PARAM_LOB); + $insert->execute(); + $insert = null; + + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + var_dump($db->query("SELECT * from test")->fetchAll(PDO::FETCH_ASSOC)); + + ?> + --XFAIL-- + This bug might be still open on aix5.2-ppc64 and hpux11.23-ia64 + --EXPECT-- + array(1) { + [0]=> + array(2) { + ["id"]=> + string(1) "1" + ["val"]=> + string(17) "I am the LOB data" + } + } + +sample018.phpt +-------------- + +.. code:: php + + --TEST-- + Phar front controller rewrite access denied [cache_list] + --INI-- + default_charset=UTF-8 + phar.cache_list={PWD}/frontcontroller10.php + --SKIPIF-- + + --ENV-- + SCRIPT_NAME=/frontcontroller10.php + REQUEST_URI=/frontcontroller10.php/hi + PATH_INFO=/hi + --FILE_EXTERNAL-- + files/frontcontroller4.phar + --EXPECTHEADERS-- + Content-type: text/html; charset=UTF-8 + Status: 403 Access Denied + --EXPECT-- + + + Access Denied + + +

403 - File /hi Access Denied

+ + + +sample019.phpt +-------------- + +.. code:: php + + --TEST-- + bzopen() and invalid parameters + --SKIPIF-- + + --FILE-- + + --EXPECTF-- + Warning: bzopen() expects exactly 2 parameters, 0 given in %s on line %d + NULL + + Warning: bzopen(): '' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(): filename cannot be empty in %s on line %d + bool(false) + + Warning: bzopen(): filename cannot be empty in %s on line %d + bool(false) + + Warning: bzopen(): 'x' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(): 'rw' is not a valid mode for bzopen(). Only 'w' and 'r' are supported. in %s on line %d + bool(false) + + Warning: bzopen(no_such_file): failed to open stream: No such file or directory in %s on line %d + bool(false) + resource(%d) of type (stream) + Done + +sample020.phpt +-------------- + +.. code:: php + + --TEST-- + Bug #42082 (NodeList length zero should be empty) + --FILE-- + query('*'); + var_dump($nodes); + var_dump($nodes->length); + $length = $nodes->length; + var_dump(empty($nodes->length), empty($length)); + + $doc->loadXML(""); + var_dump($doc->firstChild->nodeValue, empty($doc->firstChild->nodeValue), isset($doc->firstChild->nodeValue)); + var_dump(empty($doc->nodeType), empty($doc->firstChild->nodeType)) + ?> + --EXPECTF-- + object(DOMNodeList)#%d (0) { + } + int(0) + bool(true) + bool(true) + string(0) "" + bool(true) + bool(true) + bool(false) + bool(false) + +sample021.phpt +-------------- + +.. code:: php + + --TEST-- + Math constants + --INI-- + precision=14 + --FILE-- + + --EXPECTREGEX-- + M_E : 2.718281[0-9]* + M_LOG2E : 1.442695[0-9]* + M_LOG10E : 0.434294[0-9]* + M_LN2 : 0.693147[0-9]* + M_LN10 : 2.302585[0-9]* + M_PI : 3.141592[0-9]* + M_PI_2 : 1.570796[0-9]* + M_PI_4 : 0.785398[0-9]* + M_1_PI : 0.318309[0-9]* + M_2_PI : 0.636619[0-9]* + M_SQRTPI : 1.772453[0-9]* + M_2_SQRTPI: 1.128379[0-9]* + M_LNPI : 1.144729[0-9]* + M_EULER : 0.577215[0-9]* + M_SQRT2 : 1.414213[0-9]* + M_SQRT1_2 : 0.707106[0-9]* + M_SQRT3 : 1.732050[0-9]* + +sample022.phpt +-------------- + +.. code:: php + + --TEST-- + shm_detach() tests + --SKIPIF-- + + --FILE-- + + --CLEAN-- + + --EXPECTF-- + Warning: shm_detach() expects exactly 1 parameter, 0 given in %ssample022.php on line %d + NULL + + Warning: shm_detach() expects exactly 1 parameter, 2 given in %ssample022.php on line %d + NULL + bool(true) + + Warning: shm_detach(): %d is not a valid sysvshm resource in %ssample022.php on line %d + bool(false) + + Warning: shm_remove(): %d is not a valid sysvshm resource in %ssample022.php on line %d + + Warning: shm_detach() expects parameter 1 to be resource, integer given in %ssample022.php on line %d + NULL + + Warning: shm_detach() expects parameter 1 to be resource, integer given in %ssample022.php on line %d + NULL + + Warning: shm_detach() expects parameter 1 to be resource, integer given in %ssample022.php on line %d + NULL + Done + +sample023.phpt +-------------- + +.. code:: php + + --TEST-- + Bug #23894 (sprintf() decimal specifiers problem) + --FILE-- + + --EXPECTREGEX-- + string\(4\) \"-012\" + string\(8\) \"2d303132\" + (string\(13\) \" 4294967284\"|string\(20\) \"18446744073709551604\") + (string\(26\) \"20202034323934393637323834\"|string\(40\) \"3138343436373434303733373039353531363034\") + +sample024.phpt +-------------- + +.. code:: php + + --TEST-- + DOMDocument::save Test basic function of save method + --SKIPIF-- + + --FILE-- + formatOutput = true; + + $root = $doc->createElement('book'); + + $root = $doc->appendChild($root); + + $title = $doc->createElement('title'); + $title = $root->appendChild($title); + + $text = $doc->createTextNode('This is the title'); + $text = $title->appendChild($text); + + $temp_filename = __DIR__.'/DomDocument_save_basic.tmp'; + + echo 'Wrote: ' . $doc->save($temp_filename) . ' bytes'; // Wrote: 72 bytes + ?> + --CLEAN-- + + --EXPECTF-- + Wrote: 72 bytes + +sample025.phpt +-------------- + +.. code:: php + + --TEST-- + Test imap_append() function : basic functionality + --SKIPIF-- + + --FILE-- + Mailbox . "\n"; + var_dump(imap_append($imap_stream, $mb_details->Mailbox + , "From: webmaster@something.com\r\n" + . "To: info@something.com\r\n" + . "Subject: Test message\r\n" + . "\r\n" + . "this is a test message, please ignore\r\n" + )); + + var_dump(imap_append($imap_stream, $mb_details->Mailbox + , "From: webmaster@something.com\r\n" + . "To: info@something.com\r\n" + . "Subject: Another test\r\n" + . "\r\n" + . "this is another test message, please ignore it too!!\r\n" + )); + + $check = imap_check($imap_stream); + echo "Msg Count after append : ". $check->Nmsgs . "\n"; + + echo "List the msg headers\n"; + var_dump(imap_headers($imap_stream)); + + imap_close($imap_stream); + ?> + --CLEAN-- + + --EXPECTF-- + *** Testing imap_append() : basic functionality *** + Create a new mailbox for test + Create a temporary mailbox and add 0 msgs + .. mailbox '%s' created + Add a couple of msgs to new mailbox {%s}INBOX.%s + bool(true) + bool(true) + Msg Count after append : 2 + List the msg headers + array(2) { + [0]=> + string(%d) "%w%s 1)%s webmaster@something. Test message (%d chars)" + [1]=> + string(%d) "%w%s 2)%s webmaster@something. Another test (%d chars)" + } + +sample026.phpt +-------------- + +.. code:: php + + --TEST-- + SPL: ArrayIterator implementing RecursiveIterator + --FILE-- + array(21, 22 => array(221, 222), 23 => array(231)), 3); + + $dir = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY); + + foreach ($dir as $file) { + print "$file\n"; + } + + ?> + ===DONE=== + + --EXPECT-- + 1 + 21 + 221 + 222 + 231 + 3 + +skipif2.phpt +------------ + +.. code:: php + + + +skipif.phpt +----------- + +.. code:: php + + + +xfailif.phpt +------------ + +.. code:: php + + --TEST-- + Handling of errors during linking + --INI-- + opcache.enable=1 + opcache.enable_cli=1 + opcache.optimization_level=-1 + opcache.preload={PWD}/preload_inheritance_error_ind.inc + --SKIPIF-- + + --FILE-- + + --EXPECTF-- + Fatal error: Declaration of B::foo($bar) must be compatible with A::foo() in %spreload_inheritance_error.inc on line 8 From 681ef777349ced847d7cc5e511a3af413844d069 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 23 Apr 2025 17:40:56 +0100 Subject: [PATCH 405/503] Convert https://qa.php.net/running-tests.php --- docs/source/index.rst | 1 + docs/source/miscellaneous/running-tests.rst | 160 ++++++++++++++++++++ docs/source/miscellaneous/writing-tests.rst | 8 +- 3 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 docs/source/miscellaneous/running-tests.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 5d81398edef26..21e2526f47f64 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -21,6 +21,7 @@ miscellaneous/stubs miscellaneous/writing-tests + miscellaneous/running-tests Welcome to the php-src documentation! diff --git a/docs/source/miscellaneous/running-tests.rst b/docs/source/miscellaneous/running-tests.rst new file mode 100644 index 0000000000000..c85e9f4c24dea --- /dev/null +++ b/docs/source/miscellaneous/running-tests.rst @@ -0,0 +1,160 @@ +############### + Running Tests +############### + +The easiest way to test your PHP build is to run make test from the command line after successfully +compiling. This will run the all tests for all enabled functionalities and extensions located in +tests folders under the source root directory using the PHP CLI binary. + +``make test`` executes the ``run-tests.php`` script under the source root (parallel builds will not +work). Therefore you can execute the script as follows: + +.. code:: shell + + TEST_PHP_EXECUTABLE=sapi/cli/php \ + sapi/cli/php [-c /path/to/php.ini] run-tests.php [ext/foo/tests/GLOB] + +****************************************** + Which php executable does make test use? +****************************************** + +If you are running the ``run-tests.php`` script from the command line (as above) you must set the +``TEST_PHP_EXECUTABLE`` environment variable to explicitly select the PHP executable that is to be +tested, that is, used to run the test scripts. + +If you run the tests using make test, the PHP CLI and CGI executables are automatically set for you. +``make test`` executes ``run-tests.php`` script with the CLI binary. Some test scripts such as +session must be executed by CGI SAPI. Therefore, you must build PHP with CGI SAPI to perform all +tests. + +**Note:** The PHP binary executing ``run-tests.php`` and the PHP binary used for executing test +scripts may differ. If you use different PHP binary for executing ``run-tests.php`` script, you may +get errors. + +************************ + Which php.ini is used? +************************ + +``make test`` uses the same ``php.ini`` file as it would once installed. The tests have been written +to be independent of that ``php.ini`` file, so if you find a test that is affected by a setting, +please report this, so we can address the issue. + +********************************** + Which test scripts are executed? +********************************** + +The ``run-tests.php`` (``make test``), without any arguments executes all test scripts by extracting +all directories named tests from the source root and any subdirectories below. If there are files, +which have a phpt extension, ``run-tests.php`` looks at the sections in these files, determines +whether it should run it, by evaluating the ``SKIPIF`` section. If the test is eligible for +execution, the ``FILE`` section is extracted into a ``.php`` file (with the same name besides the +extension) and gets executed. When an argument is given or ``TESTS`` environment variable is set, +the GLOB is expanded by the shell and any file with extension ``*.phpt`` is regarded as a test file. + +Tester can easily execute tests selectively with as follows: + +.. code:: shell + + ./sapi/cli/php run-tests.php ext/mbstring/* + ./sapi/cli/php run-tests.php ext/mbstring/020.phpt + +************** + Test results +************** + +Test results are printed to standard output. If there is a failed test, the ``run-tests.php`` script +saves the result, the expected result and the code executed to the test script directory. For +example, if ``ext/myext/tests/myext.phpt`` fails to pass, the following files are created: + +- ``ext/myext/tests/myext.php`` - actual test file executed +- ``ext/myext/tests/myext.log`` - log of test execution (L) +- ``ext/myext/tests/myext.exp`` - expected output (E) +- ``ext/myext/tests/myext.out`` - output from test script (O) +- ``ext/myext/tests/myext.diff`` - diff of .out and .exp (D) + +Failed tests are always bugs. Either the test is bugged or not considering factors applying to the +tester's environment, or there is a bug in PHP. If this is a known bug, we strive to provide bug +numbers, in either the test name or the file name. You can check the status of such a bug, by going +to: ``https://bugs.php.net/12345`` where 12345 is the bug number. For clarity and automated +processing, bug numbers are prefixed by a hash sign '#' in test names and/or test cases are named +``bug12345.phpt``. + +**Note:** The files generated by tests can be selected by setting the environment variable +``TEST_PHP_LOG_FORMAT``. For each file you want to be generated use the character in brackets as +shown above (default is LEOD). The php file will be generated always. + +**Note**: You can set environment variable ``TEST_PHP_DETAILED`` to enable detailed test +information. + +******************* + Automated testing +******************* + +If you like to keep up to speed, with latest developments and quality assurance, setting the +environment variable ``NO_INTERACTION`` to 1, will not prompt the tester for any user input. + +Normally, the exit status of make test is zero, regardless of the results of independent tests. Set +the environment variable ``REPORT_EXIT_STATUS`` to ``1``, and make test will set the exit status +("$?") to non-zero, when an individual test has failed. + +Example script to be run by cron: + +.. code:: shell + + ========== qa-test.sh ============= + #!/bin/sh + + CO_DIR=$HOME/cvs/php7 + MYMAIL=qa-test@domain.com + TMPDIR=/var/tmp + TODAY=`date +"%Y%m%d"` + + # Make sure compilation environment is correct + CONFIGURE_OPTS='--disable-all --enable-cli --with-pcre' + export MAKE=gmake + export CC=gcc + + # Set test environment + export NO_INTERACTION=1 + export REPORT_EXIT_STATUS=1 + + cd $CO_DIR + cvs update . >>$TMPDIR/phpqatest.$TODAY + ./cvsclean ; ./buildconf ; ./configure $CONFIGURE_OPTS ; $MAKE + $MAKE test >>$TMPDIR/phpqatest.$TODAY 2>&1 + if test $? -gt 0 + then + cat $TMPDIR/phpqatest.$TODAY | mail -s"PHP-QA Test Failed for $TODAY" $MYMAIL + fi + ========== end of qa-test.sh ============= + +**Note:** The exit status of ``run-tests.php`` will be ``1`` when ``REPORT_EXIT_STATUS`` is set. The +result of make test may be higher than that. At present, gmake 3.79.1 returns 2, so it is advised to +test for non-zero, rather then a specific value. + +When ``make test`` finished running tests, and if there are any failed tests, the script asks to +send the logs to the PHP QA mailing list. Please answer ``y`` to this question so that we can +efficiently process the results, entering your e-mail address (which will not be transmitted in +plain text to any list) enables us to ask you some more information if a test failed. Note that this +script also uploads php -i output so your hostname may be transmitted. + +Specific tests can also be executed, like running tests for a certain extension. To do this you can +do like so (for example the standard library): + +.. code:: shell + + make test TESTS=ext/standard. + +Where ``TESTS=`` points to a directory containing .phpt files or a single .phpt file like: + +.. code:: shell + + make test TESTS=tests/basic/001.phpt. + +You can also pass options directly to the underlying script that runs the test suite +(``run-tests.phpt``) using ``TESTS=``, for example to check for memory leaks using Valgrind, the +``-m`` option can be passed along: ``make test TESTS="-m Zend/"``. For a full list of options that +can be passed along, then run ``make test TESTS=-h``. + +*Windows users:* On Windows the ``make`` command is called ``nmake`` instead of ``make``. This means +that on Windows you will have to run ``nmake test``, to run the test suite. diff --git a/docs/source/miscellaneous/writing-tests.rst b/docs/source/miscellaneous/writing-tests.rst index 8b5445cf4193a..fd09d80f1275e 100644 --- a/docs/source/miscellaneous/writing-tests.rst +++ b/docs/source/miscellaneous/writing-tests.rst @@ -1,6 +1,6 @@ -############ - Test Files -############ +############### + Writing Tests +############### ****************** phpt Test Basics @@ -501,7 +501,7 @@ configurations, preventing your test from failing due inconsistencies in the err Alternatively you can use ``--EXPECTF--`` and check for the message by replacing the path of the source of the message with ``%s`` and the line number with ``%d``. The end of a message in a test file ``example.phpt`` then looks like ``in %sexample.php on line %d``. We explicitly dropped the -last path devider as that is a system dependent character ``/`` or ``\``. +last path divider as that is a system dependent character ``/`` or ``\``. Last bit ======== From 0029d2b08bbd3cb3aa293d9c8d55bf31faa9e203 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 25 Apr 2025 10:20:58 +0100 Subject: [PATCH 406/503] Turn off font ligatures in code in documentation --- docs/source/_static/css/code-no-font-ligatures.css | 3 +++ docs/source/conf.py | 1 + 2 files changed, 4 insertions(+) create mode 100644 docs/source/_static/css/code-no-font-ligatures.css diff --git a/docs/source/_static/css/code-no-font-ligatures.css b/docs/source/_static/css/code-no-font-ligatures.css new file mode 100644 index 0000000000000..1ae51476f013e --- /dev/null +++ b/docs/source/_static/css/code-no-font-ligatures.css @@ -0,0 +1,3 @@ +code { + font-variant-ligatures: none; +} diff --git a/docs/source/conf.py b/docs/source/conf.py index 7347682eddf48..f28102206a9fa 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,6 +21,7 @@ templates_path = ['_templates'] html_theme = 'sphinxawesome_theme' html_static_path = ['_static'] +html_css_files = ['css/code-no-font-ligatures.css'] html_title = project html_permalinks_icon = Icons.permalinks_icon theme_options = ThemeOptions( From a91d913901a532e9fef67940942b6274a3fe2bf2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 24 Apr 2025 20:09:22 +0200 Subject: [PATCH 407/503] Fix GH-18421: Integer overflow with large numbers in LimitIterator Since we already know that `pos < intern->u.limit.offset` at this point, we can reverse the expression. Closes GH-18424. --- NEWS | 4 ++++ ext/spl/spl_iterators.c | 2 +- ext/spl/tests/gh18421.phpt | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 ext/spl/tests/gh18421.phpt diff --git a/NEWS b/NEWS index 409972a1fe9f5..bc5a597b61999 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ PHP NEWS inaccurate sunrise and sunset times, but other calculated times are correct) (JiriJozif). +- SPL: + . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). + (nielsdos) + - Standard: . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 185c844334739..d41dbee81c381 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2228,7 +2228,7 @@ static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is below the offset " ZEND_LONG_FMT, pos, intern->u.limit.offset); return; } - if (pos >= intern->u.limit.offset + intern->u.limit.count && intern->u.limit.count != -1) { + if (pos - intern->u.limit.offset >= intern->u.limit.count && intern->u.limit.count != -1) { zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is behind offset " ZEND_LONG_FMT " plus count " ZEND_LONG_FMT, pos, intern->u.limit.offset, intern->u.limit.count); return; } diff --git a/ext/spl/tests/gh18421.phpt b/ext/spl/tests/gh18421.phpt new file mode 100644 index 0000000000000..42584ef8aacc7 --- /dev/null +++ b/ext/spl/tests/gh18421.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-18421 (Integer overflow with large numbers in LimitIterator) +--FILE-- + 0, 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5); +try { + foreach (new LimitIterator(new ArrayIterator($a), PHP_INT_MAX, PHP_INT_MAX) as $k => $v) + { + } +} catch (OutOfBoundsException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +Seek position %d is out of range From 61d15870aabfb6f981c014d2dfa575a7a1d76556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 25 Apr 2025 22:57:04 +0200 Subject: [PATCH 408/503] random: Mark `mt_getrandmax()` as `@compile-time-eval` (#18425) --- ext/random/random.stub.php | 6 +++++- ext/random/random_arginfo.h | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/random/random.stub.php b/ext/random/random.stub.php index fc3b178e55fff..b59221bf9180f 100644 --- a/ext/random/random.stub.php +++ b/ext/random/random.stub.php @@ -27,9 +27,13 @@ function rand(int $min = UNKNOWN, int $max = UNKNOWN): int {} function mt_rand(int $min = UNKNOWN, int $max = UNKNOWN): int {} + /** @compile-time-eval */ function mt_getrandmax(): int {} - /** @alias mt_getrandmax */ + /** + * @compile-time-eval + * @alias mt_getrandmax + */ function getrandmax(): int {} /** @refcount 1 */ diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index 3b06d7ba9e4f3..c1cfb8eb34132 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: fad14b8b8abaf9f33d7837ba8f6190c5d10ff63f */ + * Stub hash: 8b30f08404f2912d40f4cb61b76ec283af19b79c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -160,8 +160,8 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("srand", zif_mt_srand, arginfo_srand, 0, NULL, NULL) ZEND_FE(rand, arginfo_rand) ZEND_FE(mt_rand, arginfo_mt_rand) - ZEND_FE(mt_getrandmax, arginfo_mt_getrandmax) - ZEND_RAW_FENTRY("getrandmax", zif_mt_getrandmax, arginfo_getrandmax, 0, NULL, NULL) + ZEND_RAW_FENTRY("mt_getrandmax", zif_mt_getrandmax, arginfo_mt_getrandmax, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("getrandmax", zif_mt_getrandmax, arginfo_getrandmax, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_FE(random_bytes, arginfo_random_bytes) ZEND_FE(random_int, arginfo_random_int) ZEND_FE_END From 4f10973853182b6a431e701f80e2fcac48fef581 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Apr 2025 14:11:37 +0200 Subject: [PATCH 409/503] Remove always-false intern checks (#18433) --- ext/snmp/snmp.c | 4 ---- ext/zip/php_zip.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 6cede307ac834..915c4a46e1b12 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -170,10 +170,6 @@ static void php_snmp_object_free_storage(zend_object *object) /* {{{ */ { php_snmp_object *intern = php_snmp_fetch_object(object); - if (!intern) { - return; - } - snmp_session_free(&(intern->session)); zend_object_std_dtor(&intern->zo); diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 187104d2da4ed..97a12dd4d5614 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1047,9 +1047,6 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */ ze_zip_object * intern = php_zip_fetch_object(object); int i; - if (!intern) { - return; - } if (intern->za) { if (zip_close(intern->za) != 0) { php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za)); From 7a2bef02c0106d2b98002491d4e0cfbd595abc54 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Apr 2025 12:49:47 +0200 Subject: [PATCH 410/503] Fix GH-18400: http_build_query type error is inaccurate Objects are also accepted still, so the error message is misleading. Closes GH-18434. --- NEWS | 1 + ext/standard/http.c | 2 +- ext/standard/tests/http/gh15650.phpt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 4b6e3ff84b6da..ad3bcc47ed2ba 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ PHP NEWS - Standard: . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) + . Fixed bug GH-18400 (http_build_query type error is inaccurate). (nielsdos) 24 Apr 2025, PHP 8.4.7 diff --git a/ext/standard/http.c b/ext/standard/http.c index fd862b605a7e6..5411fb3a8624f 100644 --- a/ext/standard/http.c +++ b/ext/standard/http.c @@ -246,7 +246,7 @@ PHP_FUNCTION(http_build_query) ZEND_PARSE_PARAMETERS_END(); if (UNEXPECTED(Z_TYPE_P(formdata) == IS_OBJECT && (Z_OBJCE_P(formdata)->ce_flags & ZEND_ACC_ENUM))) { - zend_argument_type_error(1, "must be of type array, %s given", zend_zval_value_name(formdata)); + zend_argument_type_error(1, "must not be an enum, %s given", zend_zval_value_name(formdata)); RETURN_THROWS(); } diff --git a/ext/standard/tests/http/gh15650.phpt b/ext/standard/tests/http/gh15650.phpt index 239e0c85164cc..69655ce407eaf 100644 --- a/ext/standard/tests/http/gh15650.phpt +++ b/ext/standard/tests/http/gh15650.phpt @@ -33,4 +33,4 @@ try { --EXPECT-- e1=hello+world%21&e2=42 ValueError: Unbacked enum E3 cannot be converted to a string -TypeError: http_build_query(): Argument #1 ($data) must be of type array, E1 given +TypeError: http_build_query(): Argument #1 ($data) must not be an enum, E1 given From b066ac0b231d3559af12e285be079c4bcb28052d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Apr 2025 12:40:38 +0200 Subject: [PATCH 411/503] Fix GH-18431: Registering ZIP progress callback twice doesn't work Libzip already cleans up the previous callback, so when that means: 1. The callback zval being already copied over the previous one causes libzip to clean up the new callback object. This is the root cause. 2. Our own code to clean the old callback is redundant. Closes GH-18432. --- NEWS | 4 ++++ ext/zip/php_zip.c | 10 ++-------- ext/zip/tests/gh18431.phpt | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 ext/zip/tests/gh18431.phpt diff --git a/NEWS b/NEWS index bc5a597b61999..c167074f0b837 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ PHP NEWS - Standard: . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) +- Zip: + . Fixed bug GH-18431 (Registering ZIP progress callback twice doesn't work). + (nielsdos) + 08 May 2025, PHP 8.3.21 - Core: diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 45b83aeae63bc..388b3485cbd94 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -3048,14 +3048,11 @@ PHP_METHOD(ZipArchive, registerProgressCallback) obj = Z_ZIP_P(self); - /* free if called twice */ - _php_zip_progress_callback_free(obj); - /* register */ - ZVAL_COPY(&obj->progress_callback, &fci.function_name); if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) { RETURN_FALSE; } + ZVAL_COPY(&obj->progress_callback, &fci.function_name); RETURN_TRUE; } @@ -3093,14 +3090,11 @@ PHP_METHOD(ZipArchive, registerCancelCallback) obj = Z_ZIP_P(self); - /* free if called twice */ - _php_zip_cancel_callback_free(obj); - /* register */ - ZVAL_COPY(&obj->cancel_callback, &fci.function_name); if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) { RETURN_FALSE; } + ZVAL_COPY(&obj->cancel_callback, &fci.function_name); RETURN_TRUE; } diff --git a/ext/zip/tests/gh18431.phpt b/ext/zip/tests/gh18431.phpt new file mode 100644 index 0000000000000..d4eb89c36c6bb --- /dev/null +++ b/ext/zip/tests/gh18431.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-18431 (Registering ZIP progress callback twice doesn't work) +--EXTENSIONS-- +zip +--FILE-- +open($file, ZIPARCHIVE::CREATE); +$zip->registerProgressCallback(0.5, $callback); +$zip->registerProgressCallback(0.5, $callback); +$zip->addFromString('foo', 'entry #1'); +?> +--CLEAN-- + +--EXPECT-- +float(0) +float(1) From e59c7f887b203d7eb8284fa5953265b7ece8e36a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 03:32:16 +0100 Subject: [PATCH 412/503] ext/libxml: Reduce scope of variables --- ext/libxml/libxml.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 429f04c00bc05..d4ea952f8a88d 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -322,10 +322,8 @@ static void php_libxml_node_free(xmlNodePtr node) PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node) { - xmlNodePtr curnode; - if (node != NULL) { - curnode = node; + xmlNodePtr curnode = node; while (curnode != NULL) { /* If the _private field is set, there's still a userland reference somewhere. We'll delay freeing in this case. */ if (curnode->_private) { @@ -1157,13 +1155,11 @@ PHP_FUNCTION(libxml_get_last_error) /* {{{ Retrieve array of errors */ PHP_FUNCTION(libxml_get_errors) { - xmlErrorPtr error; - ZEND_PARSE_PARAMETERS_NONE(); if (LIBXML(error_list)) { array_init(return_value); - error = zend_llist_get_first(LIBXML(error_list)); + xmlErrorPtr error = zend_llist_get_first(LIBXML(error_list)); while (error != NULL) { zval z_error; @@ -1285,16 +1281,15 @@ zval *php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node ex PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object) { - zend_class_entry *ce = NULL; xmlNodePtr node = NULL; - php_libxml_func_handler *export_hnd; if (Z_TYPE_P(object) == IS_OBJECT) { - ce = Z_OBJCE_P(object); + zend_class_entry *ce = Z_OBJCE_P(object); while (ce->parent != NULL) { ce = ce->parent; } - if ((export_hnd = zend_hash_find_ptr(&php_libxml_exports, ce->name))) { + php_libxml_func_handler *export_hnd = zend_hash_find_ptr(&php_libxml_exports, ce->name); + if (export_hnd) { node = export_hnd->export_func(object); } } From 1f1cd5c4bc07ea29f0211cd0e2ccbd4684e27dca Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 03:24:48 +0100 Subject: [PATCH 413/503] ext/libxml: Add some const qualifiers --- ext/libxml/libxml.c | 14 +++++++------- ext/libxml/mime_sniff.c | 4 ++-- ext/libxml/php_libxml.h | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index d4ea952f8a88d..aed8702b30e52 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -333,11 +333,11 @@ PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node) if (curnode->type == XML_ELEMENT_NODE) { /* This ensures that namespace references in this subtree are defined within this subtree, * otherwise a use-after-free would be possible when the original namespace holder gets freed. */ - php_libxml_node_ptr *ptr = curnode->_private; + const php_libxml_node_ptr *ptr = curnode->_private; /* Checking in case it runs out of reference */ if (ptr->_private) { - php_libxml_node_object *obj = ptr->_private; + const php_libxml_node_object *obj = ptr->_private; if (!obj->document || obj->document->class_type < PHP_LIBXML_CLASS_MODERN) { xmlReconciliateNs(curnode->doc, curnode); } @@ -524,7 +524,7 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) /* Check if there's been an external transport protocol with an encoding information */ if (enc == XML_CHAR_ENCODING_NONE) { - php_stream *s = (php_stream *) context; + const php_stream *s = (php_stream *) context; zend_string *charset = php_libxml_sniff_charset_from_stream(s); if (charset != NULL) { enc = xmlParseCharEncoding(ZSTR_VAL(charset)); @@ -934,7 +934,7 @@ PHP_LIBXML_API void php_libxml_shutdown(void) } } -PHP_LIBXML_API void php_libxml_switch_context(zval *context, zval *oldcontext) +PHP_LIBXML_API void php_libxml_switch_context(const zval *context, zval *oldcontext) { if (oldcontext) { ZVAL_COPY_VALUE(oldcontext, &LIBXML(stream_context)); @@ -1268,7 +1268,7 @@ int php_libxml_xmlCheckUTF8(const unsigned char *s) return 1; } -zval *php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function) +zval *php_libxml_register_export(const zend_class_entry *ce, php_libxml_export_node export_function) { php_libxml_func_handler export_hnd; @@ -1284,11 +1284,11 @@ PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object) xmlNodePtr node = NULL; if (Z_TYPE_P(object) == IS_OBJECT) { - zend_class_entry *ce = Z_OBJCE_P(object); + const zend_class_entry *ce = Z_OBJCE_P(object); while (ce->parent != NULL) { ce = ce->parent; } - php_libxml_func_handler *export_hnd = zend_hash_find_ptr(&php_libxml_exports, ce->name); + const php_libxml_func_handler *export_hnd = zend_hash_find_ptr(&php_libxml_exports, ce->name); if (export_hnd) { node = export_hnd->export_func(object); } diff --git a/ext/libxml/mime_sniff.c b/ext/libxml/mime_sniff.c index 0ca032f9b795e..14034f3db2677 100644 --- a/ext/libxml/mime_sniff.c +++ b/ext/libxml/mime_sniff.c @@ -314,8 +314,8 @@ PHP_LIBXML_API zend_string *php_libxml_sniff_charset_from_stream(const php_strea ZEND_HASH_REVERSE_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) { if (Z_TYPE_P(header) == IS_STRING) { /* If no colon is found in the header, we assume it's the HTTP status line and bail out. */ - char *colon = memchr(Z_STRVAL_P(header), ':', Z_STRLEN_P(header)); - char *space = memchr(Z_STRVAL_P(header), ' ', Z_STRLEN_P(header)); + const char *colon = memchr(Z_STRVAL_P(header), ':', Z_STRLEN_P(header)); + const char *space = memchr(Z_STRVAL_P(header), ' ', Z_STRLEN_P(header)); if (colon == NULL || space < colon) { return NULL; } diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index 3314bf6a7b28c..c05490cf5d998 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -196,7 +196,7 @@ PHP_LIBXML_API unsigned int php_libxml_increment_doc_ref(php_libxml_node_object PHP_LIBXML_API unsigned int php_libxml_decrement_doc_ref_directly(php_libxml_ref_obj *document); PHP_LIBXML_API unsigned int php_libxml_decrement_doc_ref(php_libxml_node_object *object); PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object); -PHP_LIBXML_API zval *php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function); +PHP_LIBXML_API zval *php_libxml_register_export(const zend_class_entry *ce, php_libxml_export_node export_function); /* When an explicit freeing of node and children is required */ PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node); PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node); @@ -208,7 +208,7 @@ PHP_LIBXML_API void php_libxml_pretend_ctx_error_ex(const char *file, int line, PHP_LIBXML_API void php_libxml_ctx_error(void *ctx, const char *msg, ...); PHP_LIBXML_API void php_libxml_error_handler_va(php_libxml_error_level error_type, void *ctx, const char *msg, va_list args); PHP_LIBXML_API int php_libxml_xmlCheckUTF8(const unsigned char *s); -PHP_LIBXML_API void php_libxml_switch_context(zval *context, zval *oldcontext); +PHP_LIBXML_API void php_libxml_switch_context(const zval *context, zval *oldcontext); PHP_LIBXML_API void php_libxml_issue_error(int level, const char *msg); PHP_LIBXML_API bool php_libxml_disable_entity_loader(bool disable); PHP_LIBXML_API void php_libxml_set_old_ns(xmlDocPtr doc, xmlNsPtr ns); From c5aa03c8b94efa8286d2619ec9b73769aafbf003 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 03:27:45 +0100 Subject: [PATCH 414/503] ext/libxml: Use bool type instead of int type --- ext/libxml/libxml.c | 28 ++++++++++++++-------------- ext/libxml/php_libxml.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index aed8702b30e52..21d8535f5b71b 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -49,8 +49,8 @@ #include "libxml_arginfo.h" /* a true global for initialization */ -static int php_libxml_initialized = 0; -static int php_libxml_per_request_initialization = 1; +static bool php_libxml_initialized = false; +static bool php_libxml_per_request_initialization = true; static xmlExternalEntityLoader php_libxml_default_entity_loader; typedef struct php_libxml_func_handler { @@ -404,7 +404,7 @@ PHP_LIBXML_API php_stream_context *php_libxml_get_stream_context(void) /* Channel libxml file io layer through the PHP streams subsystem. * This allows use of ftps:// and https:// urls */ -static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, const int read_only) +static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, const bool read_only) { php_stream_statbuf ssbuf; char *resolved_path; @@ -480,12 +480,12 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char static void *php_libxml_streams_IO_open_read_wrapper(const char *filename) { - return php_libxml_streams_IO_open_wrapper(filename, "rb", 1); + return php_libxml_streams_IO_open_wrapper(filename, "rb", true); } static void *php_libxml_streams_IO_open_write_wrapper(const char *filename) { - return php_libxml_streams_IO_open_wrapper(filename, "wb", 0); + return php_libxml_streams_IO_open_wrapper(filename, "wb", false); } static int php_libxml_streams_IO_read(void *context, char *buffer, int len) @@ -916,7 +916,7 @@ PHP_LIBXML_API void php_libxml_initialize(void) zend_hash_init(&php_libxml_exports, 0, NULL, php_libxml_exports_dtor, 1); - php_libxml_initialized = 1; + php_libxml_initialized = true; } } @@ -930,7 +930,7 @@ PHP_LIBXML_API void php_libxml_shutdown(void) zend_hash_destroy(&php_libxml_exports); xmlSetExternalEntityLoader(php_libxml_default_entity_loader); - php_libxml_initialized = 0; + php_libxml_initialized = false; } } @@ -962,7 +962,7 @@ static PHP_MINIT_FUNCTION(libxml) for (sapi_name = supported_sapis; *sapi_name; sapi_name++) { if (strcmp(sapi_module.name, *sapi_name) == 0) { - php_libxml_per_request_initialization = 0; + php_libxml_per_request_initialization = false; break; } } @@ -1242,7 +1242,7 @@ PHP_FUNCTION(libxml_get_external_entity_loader) /* }}} */ /* {{{ Common functions shared by extensions */ -int php_libxml_xmlCheckUTF8(const unsigned char *s) +bool php_libxml_xmlCheckUTF8(const unsigned char *s) { size_t i; unsigned char c; @@ -1251,21 +1251,21 @@ int php_libxml_xmlCheckUTF8(const unsigned char *s) if ((c & 0x80) == 0) { } else if ((c & 0xe0) == 0xc0) { if ((s[i++] & 0xc0) != 0x80) { - return 0; + return false; } } else if ((c & 0xf0) == 0xe0) { if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { - return 0; + return false; } } else if ((c & 0xf8) == 0xf0) { if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { - return 0; + return false; } } else { - return 0; + return false; } } - return 1; + return true; } zval *php_libxml_register_export(const zend_class_entry *ce, php_libxml_export_node export_function) diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index c05490cf5d998..ea7961dc2f1a7 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -207,7 +207,7 @@ PHP_LIBXML_API void php_libxml_ctx_warning(void *ctx, const char *msg, ...); PHP_LIBXML_API void php_libxml_pretend_ctx_error_ex(const char *file, int line, int column, const char *msg,...); PHP_LIBXML_API void php_libxml_ctx_error(void *ctx, const char *msg, ...); PHP_LIBXML_API void php_libxml_error_handler_va(php_libxml_error_level error_type, void *ctx, const char *msg, va_list args); -PHP_LIBXML_API int php_libxml_xmlCheckUTF8(const unsigned char *s); +PHP_LIBXML_API bool php_libxml_xmlCheckUTF8(const unsigned char *s); PHP_LIBXML_API void php_libxml_switch_context(const zval *context, zval *oldcontext); PHP_LIBXML_API void php_libxml_issue_error(int level, const char *msg); PHP_LIBXML_API bool php_libxml_disable_entity_loader(bool disable); From d1917c918ede3c6e6e5c13cc6c78b68cb71e41ff Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 03:45:02 +0100 Subject: [PATCH 415/503] ext/libxml: libxml_set_external_entity_loader() always returns true --- ext/libxml/libxml.stub.php | 2 +- ext/libxml/libxml_arginfo.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/libxml/libxml.stub.php b/ext/libxml/libxml.stub.php index 519861e918d6a..ce257b54ab4d5 100644 --- a/ext/libxml/libxml.stub.php +++ b/ext/libxml/libxml.stub.php @@ -182,6 +182,6 @@ function libxml_clear_errors(): void {} #[\Deprecated(since: '8.0', message: 'as external entity loading is disabled by default')] function libxml_disable_entity_loader(bool $disable = true): bool {} -function libxml_set_external_entity_loader(?callable $resolver_function): bool {} +function libxml_set_external_entity_loader(?callable $resolver_function): true {} function libxml_get_external_entity_loader(): ?callable {} diff --git a/ext/libxml/libxml_arginfo.h b/ext/libxml/libxml_arginfo.h index 86336d09c7d1b..b2eac9399df5c 100644 --- a/ext/libxml/libxml_arginfo.h +++ b/ext/libxml/libxml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e0d2498c10cba72adb97504fd13e178e090de2cd */ + * Stub hash: 6dceb619736a3de55b84609a9e3aeb13405bbfde */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_set_streams_context, 0, 1, IS_VOID, 0) ZEND_ARG_INFO(0, context) @@ -22,7 +22,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_disable_entity_loader, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, disable, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_set_external_entity_loader, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_set_external_entity_loader, 0, 1, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(0, resolver_function, IS_CALLABLE, 1) ZEND_END_ARG_INFO() From dc036016a39a5f89f8e4faedc6f3d1ad3d2c9d45 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 03:34:11 +0100 Subject: [PATCH 416/503] ext/libxml: Minor code nits --- ext/libxml/libxml.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 21d8535f5b71b..fa67d1d7bfbe6 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -409,7 +409,7 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char php_stream_statbuf ssbuf; char *resolved_path; const char *path_to_open = NULL; - bool isescaped = false; + bool is_escaped = false; if (strstr(filename, "%00")) { php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes"); @@ -420,7 +420,7 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char if (uri && (uri->scheme == NULL || (xmlStrncmp(BAD_CAST uri->scheme, BAD_CAST "file", 4) == 0))) { resolved_path = xmlURIUnescapeString(filename, 0, NULL); - isescaped = 1; + is_escaped = true; #if LIBXML_VERSION >= 20902 && LIBXML_VERSION < 21300 && defined(PHP_WIN32) /* Libxml 2.9.2 prefixes local paths with file:/ instead of file://, thus the php stream wrapper will fail on a valid case. For this @@ -458,7 +458,7 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char php_stream_wrapper *wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, 0); if (wrapper && read_only && wrapper->wops->url_stat) { if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssbuf, NULL) == -1) { - if (isescaped) { + if (is_escaped) { xmlFree(resolved_path); } return NULL; @@ -472,7 +472,7 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char /* Prevent from closing this by fclose() */ ret_val->flags |= PHP_STREAM_FLAG_NO_FCLOSE; } - if (isescaped) { + if (is_escaped) { xmlFree(resolved_path); } return ret_val; @@ -513,13 +513,14 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) return NULL; } - if (URI == NULL) - return(NULL); + if (URI == NULL) { + return NULL; + } context = php_libxml_streams_IO_open_read_wrapper(URI); if (context == NULL) { - return(NULL); + return NULL; } /* Check if there's been an external transport protocol with an encoding information */ @@ -544,7 +545,7 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) } else php_libxml_streams_IO_close(context); - return(ret); + return ret; } static xmlOutputBufferPtr @@ -559,8 +560,9 @@ php_libxml_output_buffer_create_filename(const char *URI, void *context = NULL; char *unescaped = NULL; - if (URI == NULL) + if (URI == NULL) { goto err; + } if (strstr(URI, "%00")) { php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes"); @@ -569,8 +571,9 @@ php_libxml_output_buffer_create_filename(const char *URI, puri = xmlParseURI(URI); if (puri != NULL) { - if (puri->scheme != NULL) + if (puri->scheme != NULL) { unescaped = xmlURIUnescapeString(URI, 0, NULL); + } xmlFreeURI(puri); } @@ -596,7 +599,7 @@ php_libxml_output_buffer_create_filename(const char *URI, ret->closecallback = php_libxml_streams_IO_close; } - return(ret); + return ret; err: /* Similarly to __xmlOutputBufferCreateFilename we should also close the encoder on failure. */ @@ -992,7 +995,7 @@ static PHP_RINIT_FUNCTION(libxml) * other threads/requests that might have disabled the loader * do not affect the current request. */ - LIBXML(entity_loader_disabled) = 0; + LIBXML(entity_loader_disabled) = false; return SUCCESS; } @@ -1094,7 +1097,7 @@ PHP_FUNCTION(libxml_use_internal_errors) RETURN_BOOL(retval); } - if (use_errors == 0) { + if (use_errors == false) { xmlSetStructuredErrorFunc(NULL, NULL); if (LIBXML(error_list)) { zend_llist_destroy(LIBXML(error_list)); @@ -1196,7 +1199,7 @@ PHP_LIBXML_API bool php_libxml_disable_entity_loader(bool disable) /* {{{ */ /* {{{ Disable/Enable ability to load external entities */ PHP_FUNCTION(libxml_disable_entity_loader) { - bool disable = 1; + bool disable = true; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL From 3932d9b660e8eb1f634118e697f973d9b24f72b2 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 12:52:35 +0100 Subject: [PATCH 417/503] ext/libxml: Get rid of useless php_libxml_func_handler abstraction --- ext/libxml/libxml.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index fa67d1d7bfbe6..6bcb092fd29d6 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -53,10 +53,6 @@ static bool php_libxml_initialized = false; static bool php_libxml_per_request_initialization = true; static xmlExternalEntityLoader php_libxml_default_entity_loader; -typedef struct php_libxml_func_handler { - php_libxml_export_node export_func; -} php_libxml_func_handler; - static HashTable php_libxml_exports; static ZEND_DECLARE_MODULE_GLOBALS(libxml) @@ -901,11 +897,6 @@ PHP_LIBXML_API void php_libxml_error_handler(void *ctx, const char *msg, ...) va_end(args); } -static void php_libxml_exports_dtor(zval *zv) -{ - free(Z_PTR_P(zv)); -} - PHP_LIBXML_API void php_libxml_initialize(void) { if (!php_libxml_initialized) { @@ -917,7 +908,7 @@ PHP_LIBXML_API void php_libxml_initialize(void) php_libxml_default_entity_loader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader(php_libxml_pre_ext_ent_loader); - zend_hash_init(&php_libxml_exports, 0, NULL, php_libxml_exports_dtor, 1); + zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1); php_libxml_initialized = true; } @@ -1273,13 +1264,10 @@ bool php_libxml_xmlCheckUTF8(const unsigned char *s) zval *php_libxml_register_export(const zend_class_entry *ce, php_libxml_export_node export_function) { - php_libxml_func_handler export_hnd; - /* Initialize in case this module hasn't been loaded yet */ php_libxml_initialize(); - export_hnd.export_func = export_function; - return zend_hash_add_mem(&php_libxml_exports, ce->name, &export_hnd, sizeof(export_hnd)); + return zend_hash_add_ptr(&php_libxml_exports, ce->name, export_function); } PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object) @@ -1291,9 +1279,9 @@ PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object) while (ce->parent != NULL) { ce = ce->parent; } - const php_libxml_func_handler *export_hnd = zend_hash_find_ptr(&php_libxml_exports, ce->name); - if (export_hnd) { - node = export_hnd->export_func(object); + const php_libxml_export_node export_function = zend_hash_find_ptr(&php_libxml_exports, ce->name); + if (export_function) { + node = export_function(object); } } return node; From c919ab4bdfaa472c95592437b1010bc284f55722 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 26 Apr 2025 13:59:38 +0100 Subject: [PATCH 418/503] [skip ci] Update UPGRADING regarding libxml signature change --- UPGRADING | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING b/UPGRADING index 68f7d20a7f32f..6fd01ab0e370f 100644 --- a/UPGRADING +++ b/UPGRADING @@ -215,6 +215,9 @@ PHP 8.5 UPGRADE NOTES . Locale:: methods throw a ValueError when locale inputs contain null bytes. +- libxml: + . libxml_set_external_entity_loader() now has a formal return type of true. + - PCNTL: . pcntl_exec() now has a formal return type of false. From 1ec9041bf8e0e22b2ba0fb0550551f049631c305 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:27:18 +0200 Subject: [PATCH 419/503] Fix reference handling in cancel callback (#18439) Broke in 8765e9f5e74651b582cd3de1218135a72dd4eea8 --- ext/zip/php_zip.c | 6 ++++-- ext/zip/tests/gh18439.phpt | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 ext/zip/tests/gh18439.phpt diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 1c2e430485884..316c22aab5f06 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -3073,10 +3073,12 @@ static int php_zip_cancel_callback(zip_t *arch, void *ptr) return -1; } bool failed = false; - zend_long retval = zval_try_get_long(&cb_retval, &failed); + zval *cb_retval_ptr = &cb_retval; + ZVAL_DEREF(cb_retval_ptr); + zend_long retval = zval_try_get_long(cb_retval_ptr, &failed); if (failed) { zend_type_error("Return value of callback provided to ZipArchive::registerCancelCallback()" - " must be of type int, %s returned", zend_zval_value_name(&cb_retval)); + " must be of type int, %s returned", zend_zval_value_name(cb_retval_ptr)); zval_ptr_dtor(&cb_retval); return -1; } diff --git a/ext/zip/tests/gh18439.phpt b/ext/zip/tests/gh18439.phpt new file mode 100644 index 0000000000000..5235bd99e47bd --- /dev/null +++ b/ext/zip/tests/gh18439.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-18439 (Reference handling in cancel callback) +--EXTENSIONS-- +zip +--FILE-- +open($file, ZIPARCHIVE::CREATE); +$zip->registerCancelCallback(cb(...)); +$zip->addFromString('test', 'test'); +echo "Done\n"; + +?> +--CLEAN-- + +--EXPECT-- +Done From 2eb3100dcaba63a394f0d0ab9993637a97d84a42 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Apr 2025 23:20:16 +0200 Subject: [PATCH 420/503] Fix GH-18438: Handling of empty data and errors in ZipArchive::addPattern There is a ZPP arginfo violation because the empty return or error return is not always properly handled. And there is also a memory leak if creating the regular expression instance fails. Closes GH-18438. --- NEWS | 2 ++ ext/zip/php_zip.c | 8 ++++++ ext/zip/tests/gh18438.phpt | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 ext/zip/tests/gh18438.phpt diff --git a/NEWS b/NEWS index c167074f0b837..efd92cb011acb 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS - Zip: . Fixed bug GH-18431 (Registering ZIP progress callback twice doesn't work). (nielsdos) + . Fixed bug GH-18438 (Handling of empty data and errors in + ZipArchive::addPattern). (nielsdos) 08 May 2025, PHP 8.3.21 diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 388b3485cbd94..62f51ce9f35f3 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -761,6 +761,10 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val re = pcre_get_compiled_regex(regexp, &capture_count); if (!re) { + for (i = 0; i < files_cnt; i++) { + zend_string_release_ex(namelist[i], 0); + } + efree(namelist); php_error_docref(NULL, E_WARNING, "Invalid expression"); return -1; } @@ -1837,6 +1841,10 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* #endif } } + } else if (found == 0) { + RETURN_EMPTY_ARRAY(); + } else { + RETURN_FALSE; } } /* }}} */ diff --git a/ext/zip/tests/gh18438.phpt b/ext/zip/tests/gh18438.phpt new file mode 100644 index 0000000000000..b997931c7088a --- /dev/null +++ b/ext/zip/tests/gh18438.phpt @@ -0,0 +1,50 @@ +--TEST-- +GH-18438 (Handling of empty data and errors in ZipArchive::addPattern) +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open($file, ZIPARCHIVE::CREATE); +var_dump($zip->addPattern('/nomatches/')); +var_dump($zip->addPattern('/invalid')); + +stream_wrapper_register('custom', CustomStreamWrapper::class); +var_dump($zip->addPattern('/invalid', 'custom://')); +?> +--CLEAN-- + +--EXPECTF-- +array(0) { +} + +Warning: ZipArchive::addPattern(): No ending delimiter '/' found in %s on line %d + +Warning: ZipArchive::addPattern(): Invalid expression in %s on line %d +bool(false) +array(0) { +} From 2beec54e47572ed8d3c4bf853047195988e4ee55 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 00:29:12 +0200 Subject: [PATCH 421/503] datefmt_parse/datefmt_localtime references type system fixes Closes GH-18441. --- NEWS | 3 ++ ext/intl/dateformat/dateformat_parse.c | 18 +++++----- .../datefmt_parse_localtime_references.phpt | 35 +++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 ext/intl/tests/datefmt_parse_localtime_references.phpt diff --git a/NEWS b/NEWS index efd92cb011acb..6d317e7507f78 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ PHP NEWS inaccurate sunrise and sunset times, but other calculated times are correct) (JiriJozif). +- Intl: + . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) + - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). (nielsdos) diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c index 69aeff886d3b9..cd6c2c35978c2 100644 --- a/ext/intl/dateformat/dateformat_parse.c +++ b/ext/intl/dateformat/dateformat_parse.c @@ -136,9 +136,9 @@ PHP_FUNCTION(datefmt_parse) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); - long_parse_pos = zval_get_long(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); @@ -151,8 +151,7 @@ PHP_FUNCTION(datefmt_parse) } internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); if(z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } /* }}} */ @@ -177,9 +176,9 @@ PHP_FUNCTION(datefmt_localtime) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); - long_parse_pos = zval_get_long(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); @@ -192,8 +191,7 @@ PHP_FUNCTION(datefmt_localtime) } internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); if (z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } /* }}} */ diff --git a/ext/intl/tests/datefmt_parse_localtime_references.phpt b/ext/intl/tests/datefmt_parse_localtime_references.phpt new file mode 100644 index 0000000000000..d9bede82ee152 --- /dev/null +++ b/ext/intl/tests/datefmt_parse_localtime_references.phpt @@ -0,0 +1,35 @@ +--TEST-- +datefmt_parse/datefmt_localtime references type system +--EXTENSIONS-- +intl +--FILE-- +prop; +$offset2 =& $test->prop; + +$fmt = datefmt_create( + 'en_US', + IntlDateFormatter::FULL, + IntlDateFormatter::FULL, + 'America/Los_Angeles', + IntlDateFormatter::GREGORIAN +); +datefmt_localtime($fmt, 'Wednesday, December 31, 1969 4:00:00 PM PT', $offset1); +datefmt_parse($fmt, 'Wednesday, December 31, 1969 4:00:00 PM PT', $offset2); +var_dump($offset1, $offset2); +var_dump($test); + +?> +--EXPECT-- +float(1) +float(1) +object(Test)#1 (1) { + ["prop"]=> + &float(1) +} From 173dccb646409945f8ed5dfef08fa68333fffcbe Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 00:13:11 +0200 Subject: [PATCH 422/503] Fix IntlDateFormatter::parseToCalendar() reference type system breaks Closes GH-18440. --- NEWS | 2 ++ ext/intl/dateformat/dateformat_parse.c | 11 ++++---- ...arseToCalendar_references_type_system.phpt | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 ext/intl/tests/parseToCalendar_references_type_system.phpt diff --git a/NEWS b/NEWS index cf676ed0dc608..1485a9f311050 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ PHP NEWS - Intl: . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) + . Fix IntlDateFormatter::parseToCalendar() reference type system breaks. + (nielsdos) - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c index b578b8bf854e6..129e007107db7 100644 --- a/ext/intl/dateformat/dateformat_parse.c +++ b/ext/intl/dateformat/dateformat_parse.c @@ -185,12 +185,12 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); bool failed = false; - long_parse_pos = zval_try_get_long(z_parse_pos, &failed); + zend_long long_parse_pos = zval_try_get_long(z_parse_pos_tmp, &failed); if (failed) { - zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); + zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos_tmp)); RETURN_THROWS(); } if (ZEND_LONG_INT_OVFL(long_parse_pos)) { @@ -205,8 +205,7 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar) } internal_parse_to_timestamp( dfo, ZSTR_VAL(text_to_parse), ZSTR_LEN(text_to_parse), z_parse_pos ? &parse_pos : NULL, true, return_value); if (z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } diff --git a/ext/intl/tests/parseToCalendar_references_type_system.phpt b/ext/intl/tests/parseToCalendar_references_type_system.phpt new file mode 100644 index 0000000000000..d0cef570842f8 --- /dev/null +++ b/ext/intl/tests/parseToCalendar_references_type_system.phpt @@ -0,0 +1,26 @@ +--TEST-- +IntlDateFormatter::parseToCalendar() reference type system breaks +--EXTENSIONS-- +intl +--FILE-- +prop; + +$oIntlDateFormatter = new IntlDateFormatter("en_GB"); +$oIntlDateFormatter->setTimeZone('Europe/Berlin'); +$oIntlDateFormatter->setPattern('VV'); +var_dump($oIntlDateFormatter->parseToCalendar('America/Los_Angeles', $offset)); +var_dump($offset); +var_dump($test); +?> +--EXPECTF-- +int(%d) +float(%f) +object(Test)#%d (1) { + ["prop"]=> + &float(%f) +} From e4f2e4a99a89022e8b4878f72879c74f56980e84 Mon Sep 17 00:00:00 2001 From: George Wang Date: Sun, 27 Apr 2025 11:20:32 -0400 Subject: [PATCH 423/503] Update SAPI_LITESPEED_PATH to sapi/litespeed/lsphp --- sapi/litespeed/config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapi/litespeed/config.m4 b/sapi/litespeed/config.m4 index f18697203cb2f..28cbd3daa6cbd 100644 --- a/sapi/litespeed/config.m4 +++ b/sapi/litespeed/config.m4 @@ -7,14 +7,14 @@ PHP_ARG_ENABLE([litespeed],, if test "$PHP_LITESPEED" != "no"; then PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/litespeed/Makefile.frag,$abs_srcdir/sapi/litespeed,sapi/litespeed) - SAPI_LITESPEED_PATH=sapi/litespeed/php + SAPI_LITESPEED_PATH=sapi/litespeed/lsphp PHP_SELECT_SAPI(litespeed, program, lsapi_main.c lsapilib.c, "", '$(SAPI_LITESPEED_PATH)') case $host_alias in *darwin*) BUILD_LITESPEED="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_LITESPEED_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)" ;; *cygwin*) - SAPI_LITESPEED_PATH=sapi/litespeed/php.exe + SAPI_LITESPEED_PATH=sapi/litespeed/lsphp.exe BUILD_LITESPEED="\$(LIBTOOL) --tag=CC --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_LITESPEED_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)" ;; *) From e961488d98de7404a97fc9494fb4f70e510bf49a Mon Sep 17 00:00:00 2001 From: George Wang Date: Sun, 27 Apr 2025 11:47:35 -0400 Subject: [PATCH 424/503] Update SAPI_LITESPEED_PATH to sapi/litespeed/lsphp --- sapi/litespeed/config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapi/litespeed/config.m4 b/sapi/litespeed/config.m4 index bb226e7482cfa..dd7265b72a7cc 100644 --- a/sapi/litespeed/config.m4 +++ b/sapi/litespeed/config.m4 @@ -8,14 +8,14 @@ if test "$PHP_LITESPEED" != "no"; then PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/litespeed/Makefile.frag], [$abs_srcdir/sapi/litespeed], [sapi/litespeed]) - SAPI_LITESPEED_PATH=sapi/litespeed/php + SAPI_LITESPEED_PATH=sapi/litespeed/lsphp PHP_SELECT_SAPI([litespeed], [program], [lsapi_main.c lsapilib.c]) AS_CASE([$host_alias], [*darwin*], [ BUILD_LITESPEED="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_LITESPEED_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)" ], [*cygwin*], [ - SAPI_LITESPEED_PATH=sapi/litespeed/php.exe + SAPI_LITESPEED_PATH=sapi/litespeed/lsphp.exe BUILD_LITESPEED="\$(LIBTOOL) --tag=CC --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_LITESPEED_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)" ], [ BUILD_LITESPEED="\$(LIBTOOL) --tag=CC --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_LITESPEED_OBJS:.lo=.o) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)" From 58e5d0c2402abf52b508e9005205eba342d83338 Mon Sep 17 00:00:00 2001 From: George Wang Date: Sun, 27 Apr 2025 11:52:51 -0400 Subject: [PATCH 425/503] Update max size of request headers from 65535 to 256K --- sapi/litespeed/lsapidef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/litespeed/lsapidef.h b/sapi/litespeed/lsapidef.h index 05c018f7ef675..22a8dec30c833 100644 --- a/sapi/litespeed/lsapidef.h +++ b/sapi/litespeed/lsapidef.h @@ -113,7 +113,7 @@ enum #define LSAPI_INTERNAL_ERROR 9 -#define LSAPI_MAX_HEADER_LEN 65535 +#define LSAPI_MAX_HEADER_LEN (1024 * 256) #define LSAPI_MAX_DATA_PACKET_LEN 16384 #define LSAPI_RESP_HTTP_HEADER_MAX 32768 From 03844d1f517017a2ef4fb9a0bac857bb5d74259d Mon Sep 17 00:00:00 2001 From: George Wang Date: Sun, 27 Apr 2025 11:59:40 -0400 Subject: [PATCH 426/503] Update LSAPI version to V8.2 --- sapi/litespeed/lsapi_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index 9c2f4e1344232..81d5d27f5cb56 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -592,7 +592,7 @@ static int sapi_lsapi_activate(void) static sapi_module_struct lsapi_sapi_module = { "litespeed", - "LiteSpeed V7.9", + "LiteSpeed V8.2", php_lsapi_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ From 6fa669a1257df260dc58fcd1cd9ffb407be0cc6a Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Sun, 27 Apr 2025 20:05:57 +0100 Subject: [PATCH 427/503] Improve PDO entry in UPGRADING file (#18446) --- UPGRADING | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/UPGRADING b/UPGRADING index 6fd01ab0e370f..befe2ac297bd6 100644 --- a/UPGRADING +++ b/UPGRADING @@ -82,8 +82,10 @@ PHP 8.5 UPGRADE NOTES emitted. To pass a variable by-ref to a constructor argument use the general array value reference assignment: $ctor_args = [&$valByRef] - . Attempting to modify a PDOStatement during a call to PDO::fetch(), - PDO::fetchObject(), PDO::fetchAll() will now throw an Error. + . Attempting to call PDOStatement::setFetchMode during a call to PDO::fetch(), + PDO::fetchObject(), PDO::fetchAll(), + for example using tricks such as passing the statement object as a constructor + argument when fetching into an object, will now throw an Error. . The value of the constants PDO::FETCH_GROUP, PDO::FETCH_UNIQUE, PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE, and PDO::FETCH_SERIALIZE has changed. From bdcea111f30fee395d5830505df5de58598abb5e Mon Sep 17 00:00:00 2001 From: tekimen Date: Mon, 28 Apr 2025 16:22:52 +0900 Subject: [PATCH 428/503] Add grapheme_levenshtein function. (#18087) Measure levenshtein for grapheme cluster unit --- NEWS | 1 + UPGRADING | 2 + ext/intl/grapheme/grapheme_string.c | 215 +++++++++++++++++++++++ ext/intl/php_intl.stub.php | 2 + ext/intl/php_intl_arginfo.h | 12 +- ext/intl/tests/grapheme_levenshtein.phpt | 128 ++++++++++++++ 6 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/grapheme_levenshtein.phpt diff --git a/NEWS b/NEWS index a3d278ac2e3b3..4d8e32cb9d02c 100644 --- a/NEWS +++ b/NEWS @@ -89,6 +89,7 @@ PHP NEWS . Added Locale::isRightToLeft to check if a locale is written right to left. (David Carlier) . Added null bytes presence in locale inputs for Locale class. (David Carlier) + . Added grapheme_levenshtein() function. (Yuya Hamada) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index befe2ac297bd6..7649f39a68508 100644 --- a/UPGRADING +++ b/UPGRADING @@ -319,6 +319,8 @@ PHP 8.5 UPGRADE NOTES - Intl: . Added locale_is_right_to_left/Locale::isRightToLeft, returns true if the locale is written right to left (after its enrichment with likely subtags). + . Added grapheme_levenshtein() function. + RFC: https://wiki.php.net/rfc/grapheme_levenshtein - Pdo\Sqlite: . Added support for Pdo\Sqlite::setAuthorizer(), which is the equivalent of diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 77bf4319928a8..08612fd1c37df 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -918,4 +918,219 @@ PHP_FUNCTION(grapheme_str_split) ubrk_close(bi); } +PHP_FUNCTION(grapheme_levenshtein) +{ + zend_string *string1, *string2; + zend_long cost_ins = 1; + zend_long cost_rep = 1; + zend_long cost_del = 1; + + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_STR(string1) + Z_PARAM_STR(string2) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(cost_ins) + Z_PARAM_LONG(cost_rep) + Z_PARAM_LONG(cost_del) + ZEND_PARSE_PARAMETERS_END(); + + if (cost_ins <= 0 || cost_ins > UINT_MAX / 4) { + zend_argument_value_error(3, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + if (cost_rep <= 0 || cost_rep > UINT_MAX / 4) { + zend_argument_value_error(4, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + if (cost_del <= 0 || cost_del > UINT_MAX / 4) { + zend_argument_value_error(5, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + zend_long c0, c1, c2; + zend_long retval; + size_t i2; + char *pstr1, *pstr2; + + UChar *ustring1 = NULL; + UChar *ustring2 = NULL; + + int32_t ustring1_len = 0; + int32_t ustring2_len = 0; + + UErrorCode ustatus = U_ZERO_ERROR; + + /* When all costs are equal, levenshtein fulfills the requirements of a metric, which means + * that the distance is symmetric. If string1 is shorter than string2 we can save memory (and CPU time) + * by having shorter rows (p1 & p2). */ + if (ZSTR_LEN(string1) < ZSTR_LEN(string2) && cost_ins == cost_rep && cost_rep == cost_del) { + zend_string *tmp = string1; + string1 = string2; + string2 = tmp; + } + + pstr1 = ZSTR_VAL(string1); + pstr2 = ZSTR_VAL(string2); + + intl_convert_utf8_to_utf16(&ustring1, &ustring1_len, pstr1, ZSTR_LEN(string1), &ustatus); + + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); + efree(ustring1); + RETURN_FALSE; + } + + intl_convert_utf8_to_utf16(&ustring2, &ustring2_len, pstr2, ZSTR_LEN(string2), &ustatus); + + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); + efree(ustring2); + efree(ustring1); + RETURN_FALSE; + } + + UBreakIterator *bi1, *bi2; + + int32_t strlen_1, strlen_2; + strlen_1 = grapheme_split_string(ustring1, ustring1_len, NULL, 0); + strlen_2 = grapheme_split_string(ustring2, ustring2_len, NULL, 0); + + if (strlen_1 == 0) { + efree(ustring1); + efree(ustring2); + RETURN_LONG(strlen_2 * cost_ins); + } + if (strlen_2 == 0) { + efree(ustring1); + efree(ustring2); + RETURN_LONG(strlen_1 * cost_del); + } + + unsigned char u_break_iterator_buffer1[U_BRK_SAFECLONE_BUFFERSIZE]; + unsigned char u_break_iterator_buffer2[U_BRK_SAFECLONE_BUFFERSIZE]; + bi1 = grapheme_get_break_iterator(u_break_iterator_buffer1, &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #1 ($string1)", 0); + efree(ustring2); + efree(ustring1); + ubrk_close(bi1); + RETURN_FALSE; + } + + bi2 = grapheme_get_break_iterator(u_break_iterator_buffer2, &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #2 ($string2)", 0); + efree(ustring2); + efree(ustring1); + ubrk_close(bi2); + ubrk_close(bi1); + RETURN_FALSE; + } + ubrk_setText(bi1, ustring1, ustring1_len, &ustatus); + + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #1 ($string1)", 0); + efree(ustring2); + efree(ustring1); + ubrk_close(bi2); + ubrk_close(bi1); + RETURN_FALSE; + } + + ubrk_setText(bi2, ustring2, ustring2_len, &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #2 ($string2)", 0); + efree(ustring2); + efree(ustring1); + ubrk_close(bi2); + ubrk_close(bi1); + RETURN_FALSE; + } + UCollator *collator = ucol_open("", &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error on ucol_open", 0); + efree(ustring2); + efree(ustring1); + ubrk_close(bi2); + ubrk_close(bi1); + ucol_close(collator); + RETURN_FALSE; + } + + zend_long *p1, *p2, *tmp; + p1 = safe_emalloc(strlen_2 + 1, sizeof(zend_long), 0); + p2 = safe_emalloc(strlen_2 + 1, sizeof(zend_long), 0); + + for (i2 = 0; i2 <= strlen_2; i2++) { + p1[i2] = i2 * cost_ins; + } + + int32_t current1 = 0; + int32_t current2 = 0; + int32_t pos1 = 0; + int32_t pos2 = 0; + + while (true) { + current1 = ubrk_current(bi1); + pos1 = ubrk_next(bi1); + if (pos1 == UBRK_DONE) { + break; + } + p2[0] = p1[0] + cost_del; + for (i2 = 0, pos2 = 0; pos2 != UBRK_DONE; i2++) { + current2 = ubrk_current(bi2); + pos2 = ubrk_next(bi2); + if (pos2 == UBRK_DONE) { + break; + } + if (ucol_strcoll(collator, ustring1 + current1, pos1 - current1, ustring2 + current2, pos2 - current2) == UCOL_EQUAL) { + c0 = p1[i2]; + } else { + c0 = p1[i2] + cost_rep; + } + c1 = p1[i2 + 1] + cost_del; + if (c1 < c0) { + c0 = c1; + } + c2 = p2[i2] + cost_ins; + if (c2 < c0) { + c0 = c2; + } + p2[i2 + 1] = c0; + } + ubrk_first(bi2); + tmp = p1; + p1 = p2; + p2 = tmp; + } + + ucol_close(collator); + + ubrk_close(bi1); + ubrk_close(bi2); + + efree(ustring1); + efree(ustring2); + + retval = p1[strlen_2]; + + efree(p1); + efree(p2); + RETURN_LONG(retval); +} + /* }}} */ diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index 4469845483e8e..7d45dcb3601f3 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -447,6 +447,8 @@ function grapheme_stristr(string $haystack, string $needle, bool $beforeNeedle = function grapheme_str_split(string $string, int $length = 1): array|false {} +function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1): int|false {} + /** @param int $next */ function grapheme_extract(string $haystack, int $size, int $type = GRAPHEME_EXTR_COUNT, int $offset = 0, &$next = null): string|false {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index bf016abf99dcb..ed4bdcded94be 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4fb44fc170e74af2e9fb52c5a1029004f708fcda */ + * Stub hash: adcf3b6ef720a518087efedbe2b62b10ad4b2624 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") @@ -489,6 +489,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_str_split, 0, 1, MAY_BE ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "1") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_levenshtein, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, string1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, string2, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, insertion_cost, IS_LONG, 0, "1") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, replacement_cost, IS_LONG, 0, "1") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, deletion_cost, IS_LONG, 0, "1") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_extract, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, haystack, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0) @@ -903,6 +911,7 @@ ZEND_FUNCTION(grapheme_substr); ZEND_FUNCTION(grapheme_strstr); ZEND_FUNCTION(grapheme_stristr); ZEND_FUNCTION(grapheme_str_split); +ZEND_FUNCTION(grapheme_levenshtein); ZEND_FUNCTION(grapheme_extract); ZEND_FUNCTION(idn_to_ascii); ZEND_FUNCTION(idn_to_utf8); @@ -1091,6 +1100,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(grapheme_strstr, arginfo_grapheme_strstr) ZEND_FE(grapheme_stristr, arginfo_grapheme_stristr) ZEND_FE(grapheme_str_split, arginfo_grapheme_str_split) + ZEND_FE(grapheme_levenshtein, arginfo_grapheme_levenshtein) ZEND_FE(grapheme_extract, arginfo_grapheme_extract) ZEND_FE(idn_to_ascii, arginfo_idn_to_ascii) ZEND_FE(idn_to_utf8, arginfo_idn_to_utf8) diff --git a/ext/intl/tests/grapheme_levenshtein.phpt b/ext/intl/tests/grapheme_levenshtein.phpt new file mode 100644 index 0000000000000..4ff7dbb607bcd --- /dev/null +++ b/ext/intl/tests/grapheme_levenshtein.phpt @@ -0,0 +1,128 @@ +--TEST-- +grapheme_levenshtein() function test +--EXTENSIONS-- +intl +--FILE-- +getMessage() . PHP_EOL; +} + +try { + grapheme_levenshtein($nabe, $nabe_E0100, 1, 0, 1); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + grapheme_levenshtein($nabe, $nabe_E0100, 1, 1, 0); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +?> +--EXPECTF-- +--- Equal --- +int(0) +--- First string empty --- +int(3) +--- Second string empty --- +int(3) +--- Both empty --- +int(0) +int(0) +--- 1 character --- +int(1) +--- 2 character swapped --- +int(2) +--- Inexpensive deletion --- +int(2) +--- Expensive deletion --- +int(10) +--- Inexpensive insertion --- +int(2) +--- Expensive insertion --- +int(10) +--- Expensive replacement --- +int(3) +--- Very expensive replacement --- +int(4) +--- 128 codepoints --- +int(2) +--- 128 codepoints over --- +int(2) +int(256) +--- 128 codepoints over only $string1 --- +int(128) +--- 128 codepoints over only $string2 --- +int(130) +--- 128 codepoints over Hiragana --- +int(2) +--- Variable selector --- +int(1) +int(0) +int(0) +--- Corner case --- +grapheme_levenshtein(): Argument #3 ($insertion_cost) must be greater than 0 and less than or equal to %d +grapheme_levenshtein(): Argument #4 ($replacement_cost) must be greater than 0 and less than or equal to %d +grapheme_levenshtein(): Argument #5 ($deletion_cost) must be greater than 0 and less than or equal to %d From 0a42e6fbc5476638aed2403288c9b84103c95459 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 24 Apr 2025 12:25:06 +0200 Subject: [PATCH 429/503] Use --ignore-platform-req=php+ in community build --ignore-platform-reqs may accidentally install versions of dependencies that no longer support the given PHP version. --ignore-platform-req=php+ will only suppress errors for new PHP version but not change behavior for older versions. Thanks to Tim for the hint. Also skip the Laravel build for PHP 8.1, which is no longer supported on Laravel's default branch. --- .github/workflows/nightly.yml | 21 ++++++++++++--------- .github/workflows/root.yml | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c9e6850604312..1b1532af7f799 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -29,6 +29,9 @@ on: windows_version: required: true type: string + skip_laravel: + required: true + type: boolean skip_symfony: required: true type: boolean @@ -550,7 +553,7 @@ jobs: git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1 cd "amphp-$repository" git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ vendor/bin/phpunit || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; @@ -559,12 +562,12 @@ jobs: done exit $X - name: Test Laravel - if: ${{ !cancelled() }} + if: ${{ !cancelled() && !inputs.skip_laravel }} run: | git clone https://github.com/laravel/framework.git --depth=1 cd framework git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ # Hack to disable a test that hangs php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$? @@ -581,7 +584,7 @@ jobs: git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1 cd "reactphp-$repository" git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ vendor/bin/phpunit || EXIT_CODE=$? if [ $[EXIT_CODE:-0} -gt 128 ]; then X=1; @@ -595,7 +598,7 @@ jobs: git clone https://github.com/revoltphp/event-loop.git --depth=1 cd event-loop git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ vendor/bin/phpunit || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 @@ -606,7 +609,7 @@ jobs: git clone https://github.com/symfony/symfony.git --depth=1 cd symfony git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ php ./phpunit install # Test causes a heap-buffer-overflow but I cannot reproduce it locally... php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "/** @group skip */\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' @@ -627,7 +630,7 @@ jobs: git clone https://github.com/sebastianbergmann/phpunit.git --branch=main --depth=1 cd phpunit git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ php ./phpunit || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 @@ -635,7 +638,7 @@ jobs: - name: 'Symfony Preloading' if: ${{ !cancelled() && !inputs.skip_symfony }} run: | - php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-reqs + php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-req=php+ cd symfony_demo git rev-parse HEAD sed -i 's/PHP_SAPI/"cli-server"/g' var/cache/dev/App_KernelDevDebugContainer.preload.php @@ -646,7 +649,7 @@ jobs: git clone https://github.com/WordPress/wordpress-develop.git wordpress --depth=1 cd wordpress git rev-parse HEAD - php /usr/bin/composer install --no-progress --ignore-platform-reqs + php /usr/bin/composer install --no-progress --ignore-platform-req=php+ cp wp-tests-config-sample.php wp-tests-config.php sed -i 's/youremptytestdbnamehere/test/g' wp-tests-config.php sed -i 's/yourusernamehere/root/g' wp-tests-config.php diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 2bb895e96b668..a98bb39ba0d92 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -59,6 +59,7 @@ jobs: (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') || '22.04' }} windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} + skip_laravel: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_symfony: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_wordpress: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} secrets: inherit From 7869af6fa85cb60cedb739e59af405318e196d78 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 15:50:12 +0200 Subject: [PATCH 430/503] Fix GH-18417: Windows SHM reattachment fails when increasing memory_consumption or jit_buffer_size When a first PHP process launches, Opcache creates a shared file mapping to use as a shm region. The size of this mapping is set by opcache.memory_consumption. When a new PHP process launches while the old one is still running, Opcache tries to reattach to the shm. When reattaching it tries to map the requested size (i.e. set by opcache.memory_consumption). However, if the new requested size is larger than the size used in the original file mapping, then the call to VirtualProtect() will fail and the new PHP process will fail to launch. It's not possible to resize the virtual region on Windows, unless relying on undocumented APIs like `NtExtendSection` but then we would sitll need to communicate that to the first process. This issue is the root cause of Psalm end-to-end tests failing in GH-18417: Psalm estimates the required memory sizes and relaunches itself with more memory requested, if its estimate is below the currently allocated shared memory. This causes a crash on startup and the tests fail. To solve this, we need to make the mappings unique per requested size. There are two ideas: 1. Include in zend_system_id. However, this also affects other things and may be too overkill. 2. Include it in the filename, this is an easy local change. I went with this option. Closes GH-18443. --- NEWS | 4 ++++ ext/opcache/shared_alloc_win32.c | 16 ++++++++----- ext/opcache/tests/gh18417.phpt | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 ext/opcache/tests/gh18417.phpt diff --git a/NEWS b/NEWS index 6d317e7507f78..a2c4da767ec6b 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ PHP NEWS - Intl: . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) +- Opcache: + . Fixed bug GH-18417 (Windows SHM reattachment fails when increasing + memory_consumption or jit_buffer_size). (nielsdos) + - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). (nielsdos) diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index 893fe98ec189c..b24401e3d305d 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -69,9 +69,9 @@ static void zend_win_error_message(int type, char *msg, int err) php_win32_error_msg_free(buf); } -static char *create_name_with_username(char *name) +static char *create_name_with_username(const char *name, size_t unique_id) { - static char newname[MAXPATHLEN + 1 + 32 + 1 + 20 + 1 + 32 + 1]; + static char newname[MAXPATHLEN + 1 + 32 + 1 + 20 + 1 + 32 + sizeof("ffffffffffffffff")-1 + 1]; char *p = newname; p += strlcpy(newname, name, MAXPATHLEN + 1); *(p++) = '@'; @@ -82,7 +82,11 @@ static char *create_name_with_username(char *name) *(p++) = '@'; memcpy(p, zend_system_id, 32); p += 32; - *(p++) = '\0'; + if (unique_id) { + p += snprintf(p, sizeof("ffffffffffffffff"), "%zx", unique_id) + 1; + } else { + *(p++) = '\0'; + } ZEND_ASSERT(p - newname <= sizeof(newname)); return newname; @@ -90,7 +94,7 @@ static char *create_name_with_username(char *name) void zend_shared_alloc_create_lock(void) { - memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME)); + memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME, 0)); if (!memory_mutex) { zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex (error %u)", GetLastError()); return; @@ -224,7 +228,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ can be called before the child process is killed. In this case, the mapping will fail and we have to sleep some time (until the child releases the mapping object) and retry.*/ do { - memfile = OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE|FILE_MAP_EXECUTE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); + memfile = OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE|FILE_MAP_EXECUTE, 0, create_name_with_username(ACCEL_FILEMAP_NAME, requested_size)); if (memfile == NULL) { err = GetLastError(); break; @@ -269,7 +273,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ (*shared_segments_p)[0] = shared_segment; memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE | SEC_COMMIT, size_high, size_low, - create_name_with_username(ACCEL_FILEMAP_NAME)); + create_name_with_username(ACCEL_FILEMAP_NAME, requested_size)); if (memfile == NULL) { err = GetLastError(); zend_shared_alloc_unlock_win32(); diff --git a/ext/opcache/tests/gh18417.phpt b/ext/opcache/tests/gh18417.phpt new file mode 100644 index 0000000000000..e7b9790b9e661 --- /dev/null +++ b/ext/opcache/tests/gh18417.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-18417 (Windows SHM reattachment fails when increasing memory_consumption or jit_buffer_size) +--SKIPIF-- + +--FILE-- + ["pipe", "r"], + 1 => ["pipe", "w"], + 2 => ["pipe", "w"], +]; + +$proc = proc_open([ + PHP_BINARY, + "-n", + "-d", "extension_dir=$extension_dir", + "-d", "zend_extension=opcache", + "-d", "opcache.memory_consumption=$new_memory_consumption", + "-d", "opcache.enable=1", + "-d", "opcache.enable_cli=1", + "-r", + "echo 1;" +], $descriptorspec, $pipes); + +echo stream_get_contents($pipes[1]); +echo stream_get_contents($pipes[2]); + +proc_close($proc); +?> +--EXPECT-- +1 From 978c01ce158897498f07cff6a0465305647c8f8f Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 10 Apr 2025 16:22:08 +0200 Subject: [PATCH 431/503] JIT: Check exception on exit Add a new exit flag (ZEND_JIT_EXIT_CHECK_EXCEPTION) that enables exception checking during exit/deoptimization. We already checked for exceptions during exit/deoptimization, but only when ZEND_JIT_EXIT_FREE_OP1 or ZEND_JIT_EXIT_FREE_OP2 were set (presumably to handle exceptions thrown during dtor). The new flag makes it possible to request it explicitly. This also fixes two issues in zend_jit_trace_exit(): - By returning 1, we were telling the caller (zend_jit_trace_exit_stub()) to execute the original op handler of EG(current_execute_data)->opline, but in reality we want to execute EX(opline), which should be EG(exception_op). - EX(opline) is set to the value of %r15 in zend_jit_trace_exit_stub() before calling zend_jit_trace_exit(), but this may be the address of a zend_execute_data when the register is being reused to cache EX(call). Fixes GH-18262 Closes GH-18297 --- NEWS | 2 ++ ext/opcache/jit/zend_jit_internal.h | 23 ++++++++-------- ext/opcache/jit/zend_jit_ir.c | 4 +-- ext/opcache/jit/zend_jit_trace.c | 16 ++++++++--- ext/opcache/tests/jit/gh18262-001.phpt | 37 ++++++++++++++++++++++++++ ext/opcache/tests/jit/gh18262-002.phpt | 34 +++++++++++++++++++++++ ext/opcache/tests/jit/gh18262-003.phpt | 35 ++++++++++++++++++++++++ ext/opcache/tests/jit/gh18262-004.phpt | 36 +++++++++++++++++++++++++ 8 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 ext/opcache/tests/jit/gh18262-001.phpt create mode 100644 ext/opcache/tests/jit/gh18262-002.phpt create mode 100644 ext/opcache/tests/jit/gh18262-003.phpt create mode 100644 ext/opcache/tests/jit/gh18262-004.phpt diff --git a/NEWS b/NEWS index af78129214f7d..2331df67b60ec 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS - Opcache: . Fixed bug GH-18417 (Windows SHM reattachment fails when increasing memory_consumption or jit_buffer_size). (nielsdos) + . Fixed bug GH-18297 (Exception not handled when jit guard is triggered). + (Arnaud) - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index ce245bdb1988e..1bf62e1f91452 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -311,17 +311,18 @@ typedef enum _zend_jit_trace_stop { #define ZEND_JIT_TRACE_SUPPORTED 0 -#define ZEND_JIT_EXIT_JITED (1<<0) -#define ZEND_JIT_EXIT_BLACKLISTED (1<<1) -#define ZEND_JIT_EXIT_TO_VM (1<<2) /* exit to VM without attempt to create a side trace */ -#define ZEND_JIT_EXIT_RESTORE_CALL (1<<3) /* deoptimizer should restore EX(call) chain */ -#define ZEND_JIT_EXIT_POLYMORPHISM (1<<4) /* exit because of polymorphic call */ -#define ZEND_JIT_EXIT_FREE_OP1 (1<<5) -#define ZEND_JIT_EXIT_FREE_OP2 (1<<6) -#define ZEND_JIT_EXIT_PACKED_GUARD (1<<7) -#define ZEND_JIT_EXIT_CLOSURE_CALL (1<<8) /* exit because of polymorphic INIT_DYNAMIC_CALL call */ -#define ZEND_JIT_EXIT_METHOD_CALL (1<<9) /* exit because of polymorphic INIT_METHOD_CALL call */ -#define ZEND_JIT_EXIT_INVALIDATE (1<<10) /* invalidate current trace */ +#define ZEND_JIT_EXIT_JITED (1<<0) +#define ZEND_JIT_EXIT_BLACKLISTED (1<<1) +#define ZEND_JIT_EXIT_TO_VM (1<<2) /* exit to VM without attempt to create a side trace */ +#define ZEND_JIT_EXIT_RESTORE_CALL (1<<3) /* deoptimizer should restore EX(call) chain */ +#define ZEND_JIT_EXIT_POLYMORPHISM (1<<4) /* exit because of polymorphic call */ +#define ZEND_JIT_EXIT_FREE_OP1 (1<<5) +#define ZEND_JIT_EXIT_FREE_OP2 (1<<6) +#define ZEND_JIT_EXIT_PACKED_GUARD (1<<7) +#define ZEND_JIT_EXIT_CLOSURE_CALL (1<<8) /* exit because of polymorphic INIT_DYNAMIC_CALL call */ +#define ZEND_JIT_EXIT_METHOD_CALL (1<<9) /* exit because of polymorphic INIT_METHOD_CALL call */ +#define ZEND_JIT_EXIT_INVALIDATE (1<<10) /* invalidate current trace */ +#define ZEND_JIT_EXIT_CHECK_EXCEPTION (1<<11) #define ZEND_JIT_EXIT_FIXED (1U<<31) /* the exit_info can't be changed by zend_jit_snapshot_handler() */ diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index e9b1a9f01e184..064e88c39c14b 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -14483,12 +14483,12 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, ZEND_ASSERT(end_inputs == IR_UNUSED); if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame)) { uint8_t type = concrete_type(res_info); - uint32_t flags = 0; + uint32_t flags = ZEND_JIT_EXIT_CHECK_EXCEPTION; if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !delayed_fetch_this && !op1_avoid_refcounting) { - flags = ZEND_JIT_EXIT_FREE_OP1; + flags |= ZEND_JIT_EXIT_FREE_OP1; } if ((opline->result_type & (IS_VAR|IS_TMP_VAR)) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 4ee0a8a413c8e..c0ee09e6e6315 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3474,7 +3474,7 @@ static int zend_jit_trace_exit_needs_deoptimization(uint32_t trace_num, uint32_t uint32_t stack_size; zend_jit_trace_stack *stack; - if (opline || (flags & (ZEND_JIT_EXIT_RESTORE_CALL|ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2))) { + if (opline || (flags & (ZEND_JIT_EXIT_RESTORE_CALL|ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2|ZEND_JIT_EXIT_CHECK_EXCEPTION))) { return 1; } @@ -3634,7 +3634,7 @@ static int zend_jit_trace_deoptimization( } } - if (flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) { + if (flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2|ZEND_JIT_EXIT_CHECK_EXCEPTION)) { zend_jit_check_exception(jit); } @@ -7943,6 +7943,9 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t) if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP2) { fprintf(stderr, "/FREE_OP2"); } + if (t->exit_info[i].flags & ZEND_JIT_EXIT_CHECK_EXCEPTION) { + fprintf(stderr, "/CHK_EXC"); + } for (j = 0; j < stack_size; j++) { uint8_t type = STACK_TYPE(stack, j); if (type != IS_UNKNOWN) { @@ -8654,9 +8657,14 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf EX(opline) = opline-1; zval_ptr_dtor_nogc(EX_VAR((opline-1)->op1.var)); } - if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) { + if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2|ZEND_JIT_EXIT_CHECK_EXCEPTION)) { if (EG(exception)) { - return 1; + /* EX(opline) was overridden in zend_jit_trace_exit_stub(), + * and may be wrong when IP is reused. */ + if (GCC_GLOBAL_REGS) { + EX(opline) = EG(exception_op); + } + return 0; } } if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_METHOD_CALL) { diff --git a/ext/opcache/tests/jit/gh18262-001.phpt b/ext/opcache/tests/jit/gh18262-001.phpt new file mode 100644 index 0000000000000..345b56a5e517c --- /dev/null +++ b/ext/opcache/tests/jit/gh18262-001.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-18262 001 (Assertion failure Zend/zend_vm_execute.h JIT) +--CREDITS-- +YuanchengJiang +--FILE-- +newLazyProxy(function ($obj) use ($instance) { + $instance->b = 1; + return $instance; + }); + var_dump($obj->b); +} +?> +--EXPECTF-- +int(1) +int(1) + +Fatal error: Uncaught TypeError: %s in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/opcache/tests/jit/gh18262-002.phpt b/ext/opcache/tests/jit/gh18262-002.phpt new file mode 100644 index 0000000000000..b82723abaa29a --- /dev/null +++ b/ext/opcache/tests/jit/gh18262-002.phpt @@ -0,0 +1,34 @@ +--TEST-- +GH-18262 002 (Assertion failure Zend/zend_vm_execute.h JIT) +--FILE-- +b = $init; + } + } +} + +$tests = [ + new B(1), + new B(0), +]; + +set_error_handler(function ($_, $errstr) { + throw new \Exception($errstr); +}); + +foreach ($tests as $obj) { + var_dump($obj->b); +} +?> +--EXPECTF-- +int(1) + +Fatal error: Uncaught Exception: Undefined property: B::$b in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(2, 'Undefined prope...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/ext/opcache/tests/jit/gh18262-003.phpt b/ext/opcache/tests/jit/gh18262-003.phpt new file mode 100644 index 0000000000000..a3c3e037632f9 --- /dev/null +++ b/ext/opcache/tests/jit/gh18262-003.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-18262 003 (Assertion failure Zend/zend_vm_execute.h JIT) +--FILE-- +b = $init; + } + } +} + +$tests = [ + new B(1), + new B('str'), // slow deoptimization, create linked side trace + new B(0), // jump to side trace with fast deoptimization +]; + +set_error_handler(function ($_, $errstr) { + throw new \Exception($errstr); +}); + +foreach ($tests as $obj) { + try { + var_dump($obj->b); + } catch (Exception $e) { + printf("%s: %s\n", $e::class, $e->getMessage()); + } +} +?> +--EXPECT-- +int(1) +string(3) "str" +Exception: Undefined property: B::$b diff --git a/ext/opcache/tests/jit/gh18262-004.phpt b/ext/opcache/tests/jit/gh18262-004.phpt new file mode 100644 index 0000000000000..c8dccd30c98ae --- /dev/null +++ b/ext/opcache/tests/jit/gh18262-004.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-18262 004 (Assertion failure Zend/zend_vm_execute.h JIT) +--FILE-- +throw === '1' ? 'str' : 1; + } + public function __destruct() { + if ($this->throw === '1') { + throw new Exception(__METHOD__); + } + } +} + +$tests = [ + '0', + '1', +]; + +foreach ($tests as $test) { + // Second iteration exits, and free op1 throws + var_dump((new B($test))->b); +} +?> +--EXPECTF-- +int(1) + +Fatal error: Uncaught Exception: B::__destruct in %s:%d +Stack trace: +#0 %s(%d): B->__destruct() +#1 {main} + thrown in %s on line %d From 0eea5d31e0fc39c5c67c9035508a0bbb49232036 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com> Date: Tue, 29 Apr 2025 10:59:10 +0200 Subject: [PATCH 432/503] run-tests.php: Remove extra env vars in the generated .sh file (#18306) --- run-tests.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/run-tests.php b/run-tests.php index a90681c7ff7f1..036162725673f 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2735,8 +2735,14 @@ function run_test(string $php, $file, array $env): string if (!$passed || $leaked) { // write .sh if (strpos($log_format, 'S') !== false) { - $env_lines = []; + // Unset all environment variables so that we don't inherit extra + // ones from the parent process. + $env_lines = ['unset $(env | cut -d= -f1)']; foreach ($env as $env_var => $env_val) { + if (strval($env_val) === '') { + // proc_open does not pass empty env vars + continue; + } $env_lines[] = "export $env_var=" . escapeshellarg($env_val ?? ""); } $exported_environment = "\n" . implode("\n", $env_lines) . "\n"; @@ -2745,7 +2751,7 @@ function run_test(string $php, $file, array $env): string {$exported_environment} case "$1" in "gdb") - gdb --args {$orig_cmd} + gdb -ex 'unset environment LINES' -ex 'unset environment COLUMNS' --args {$orig_cmd} ;; "lldb") lldb -- {$orig_cmd} From 2fea4efa8f2821bf3cf767a73c1bef2c7b0a1791 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com> Date: Tue, 29 Apr 2025 17:06:59 +0200 Subject: [PATCH 433/503] Fix merge error (#18453) --- ext/opcache/jit/zend_jit_trace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index faa88cc6b2e56..a2c3c7fa0fbb4 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8731,9 +8731,7 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf if (EG(exception)) { /* EX(opline) was overridden in zend_jit_trace_exit_stub(), * and may be wrong when IP is reused. */ - if (GCC_GLOBAL_REGS) { - EX(opline) = EG(exception_op); - } + EX(opline) = EG(exception_op); return 0; } } From 3f03f7ed3d988567b5a59ae542579fd91cdfde42 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Tue, 29 Apr 2025 11:53:09 -0700 Subject: [PATCH 434/503] [RFC] Add support for attributes on compile-time constants https://wiki.php.net/rfc/attributes-on-constants --- UPGRADING | 6 + Zend/tests/attributes/001_placement.phpt | 14 +- .../029_reflect_internal_symbols.phpt | 5 + Zend/tests/attributes/034_target_values.phpt | 39 + .../constants/allow_named_parameters.phpt | 39 + .../attributes/constants/ast_export.phpt | 34 + .../constant_listed_as_target-internal.phpt | 11 + .../constant_listed_as_target-userland.phpt | 31 + .../constant_redefined_addition.phpt | 21 + .../constants/constant_redefined_change.phpt | 27 + .../constants/constant_redefined_removal.phpt | 26 + .../multiple_attributes_grouped.phpt | 25 + .../multiple_attributes_ungrouped.phpt | 26 + .../constants/multiple_constants_error.phpt | 12 + .../constants/must_target_const-internal.phpt | 11 + .../constants/must_target_const-userland.phpt | 31 + .../constants/not_repeatable-internal.phpt | 12 + .../constants/not_repeatable-userland.phpt | 36 + .../constants/repeatable-internal.phpt | 16 + .../constants/repeatable-userland.phpt | 30 + .../target_all_targets_const-default.phpt | 25 + .../target_all_targets_const-explicit.phpt | 25 + .../deprecated/constants/const_messages.phpt | 49 + .../deprecated_constant_as_message_001.phpt | 24 + .../deprecated_constant_as_message_002.phpt | 34 + .../deprecated_constant_as_message_003.phpt | 21 + .../deprecated/constants/error_code.phpt | 19 + .../value_unknown_at_compile_time_001.phpt | 19 + Zend/zend_ast.c | 37 +- Zend/zend_attributes.c | 3 +- Zend/zend_attributes.h | 7 +- Zend/zend_attributes.stub.php | 4 +- Zend/zend_attributes_arginfo.h | 10 +- Zend/zend_compile.c | 33 +- Zend/zend_compile.h | 5 + Zend/zend_constants.c | 37 +- Zend/zend_constants.h | 2 + Zend/zend_execute.c | 24 +- Zend/zend_execute.h | 2 + Zend/zend_execute_API.c | 3 + Zend/zend_language_parser.y | 2 +- Zend/zend_opcode.c | 12 + Zend/zend_vm_def.h | 43 + Zend/zend_vm_execute.h | 233 +++-- Zend/zend_vm_handlers.h | 923 +++++++++--------- Zend/zend_vm_opcodes.c | 6 +- Zend/zend_vm_opcodes.h | 3 +- .../core/data-structures/zend_constant.rst | 19 +- ext/opcache/jit/zend_jit_trace.c | 1 + ext/opcache/jit/zend_jit_vm_helpers.c | 10 +- ext/opcache/zend_file_cache.c | 27 + ext/opcache/zend_persist.c | 8 + ext/opcache/zend_persist_calc.c | 15 + ext/reflection/php_reflection.c | 12 + ext/reflection/php_reflection.stub.php | 2 + ext/reflection/php_reflection_arginfo.h | 6 +- .../ReflectionConstant_getAttributes.phpt | 19 + ...eflectionConstant_getAttributes_empty.phpt | 24 + ...lectionConstant_isDeprecated_userland.phpt | 13 + ext/zend_test/test.c | 19 + ext/zend_test/test.stub.php | 2 + ext/zend_test/test_arginfo.h | 6 +- .../tests/compile_to_ast/basic_ast.phpt | 54 + .../compile_to_ast/complicated_class.phpt | 89 ++ ext/zend_test/tests/compile_to_ast/enum.phpt | 54 + sapi/phpdbg/phpdbg.c | 3 +- 66 files changed, 1859 insertions(+), 581 deletions(-) create mode 100644 Zend/tests/attributes/034_target_values.phpt create mode 100644 Zend/tests/attributes/constants/allow_named_parameters.phpt create mode 100644 Zend/tests/attributes/constants/ast_export.phpt create mode 100644 Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt create mode 100644 Zend/tests/attributes/constants/constant_listed_as_target-userland.phpt create mode 100644 Zend/tests/attributes/constants/constant_redefined_addition.phpt create mode 100644 Zend/tests/attributes/constants/constant_redefined_change.phpt create mode 100644 Zend/tests/attributes/constants/constant_redefined_removal.phpt create mode 100644 Zend/tests/attributes/constants/multiple_attributes_grouped.phpt create mode 100644 Zend/tests/attributes/constants/multiple_attributes_ungrouped.phpt create mode 100644 Zend/tests/attributes/constants/multiple_constants_error.phpt create mode 100644 Zend/tests/attributes/constants/must_target_const-internal.phpt create mode 100644 Zend/tests/attributes/constants/must_target_const-userland.phpt create mode 100644 Zend/tests/attributes/constants/not_repeatable-internal.phpt create mode 100644 Zend/tests/attributes/constants/not_repeatable-userland.phpt create mode 100644 Zend/tests/attributes/constants/repeatable-internal.phpt create mode 100644 Zend/tests/attributes/constants/repeatable-userland.phpt create mode 100644 Zend/tests/attributes/constants/target_all_targets_const-default.phpt create mode 100644 Zend/tests/attributes/constants/target_all_targets_const-explicit.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/const_messages.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_001.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_003.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/error_code.phpt create mode 100644 Zend/tests/attributes/deprecated/constants/value_unknown_at_compile_time_001.phpt create mode 100644 ext/reflection/tests/ReflectionConstant_getAttributes.phpt create mode 100644 ext/reflection/tests/ReflectionConstant_getAttributes_empty.phpt create mode 100644 ext/reflection/tests/ReflectionConstant_isDeprecated_userland.phpt create mode 100644 ext/zend_test/tests/compile_to_ast/basic_ast.phpt create mode 100644 ext/zend_test/tests/compile_to_ast/complicated_class.phpt create mode 100644 ext/zend_test/tests/compile_to_ast/enum.phpt diff --git a/UPGRADING b/UPGRADING index 7649f39a68508..199162177fe99 100644 --- a/UPGRADING +++ b/UPGRADING @@ -133,6 +133,10 @@ PHP 8.5 UPGRADE NOTES . Added asymmetric visibility support for static properties. RFC: https://wiki.php.net/rfc/static-aviz . Added support for casts in constant expressions. + . Added support for attributes on compile-time non-class constants. + RFC: https://wiki.php.net/rfc/attributes-on-constants + . The #[\Deprecated] attribute can now be used on constants. + RFC: https://wiki.php.net/rfc/attributes-on-constants - Curl: . Added support for share handles that are persisted across multiple PHP @@ -337,6 +341,8 @@ PHP 8.5 UPGRADE NOTES . ReflectionConstant::getFileName() was introduced. . ReflectionConstant::getExtension() and ReflectionConstant::getExtensionName() were introduced. + . ReflectionConstant::getAttributes() was introduced. + RFC: https://wiki.php.net/rfc/attributes-on-constants ======================================== 7. New Classes and Interfaces diff --git a/Zend/tests/attributes/001_placement.phpt b/Zend/tests/attributes/001_placement.phpt index 518c890ef2c4a..3162aca61a726 100644 --- a/Zend/tests/attributes/001_placement.phpt +++ b/Zend/tests/attributes/001_placement.phpt @@ -25,6 +25,9 @@ $f2 = #[A1(9)] function () { }; $f3 = #[A1(10)] fn () => 1; +#[A1(11)] +const CT_CONSTANT = 'Demo'; + $ref = new \ReflectionClass(Foo::class); $sources = [ @@ -37,7 +40,8 @@ $sources = [ new \ReflectionObject($object), new \ReflectionFunction('f1'), new \ReflectionFunction($f2), - new \ReflectionFunction($f3) + new \ReflectionFunction($f3), + new \ReflectionConstant('CT_CONSTANT'), ]; foreach ($sources as $r) { @@ -132,3 +136,11 @@ array(1) { [0]=> int(10) } + +string(18) "ReflectionConstant" +int(1) +string(2) "A1" +array(1) { + [0]=> + int(11) +} diff --git a/Zend/tests/attributes/029_reflect_internal_symbols.phpt b/Zend/tests/attributes/029_reflect_internal_symbols.phpt index d4dc29a0bb997..fdc06cd49db9a 100644 --- a/Zend/tests/attributes/029_reflect_internal_symbols.phpt +++ b/Zend/tests/attributes/029_reflect_internal_symbols.phpt @@ -18,6 +18,9 @@ var_dump($rcc->getAttributes()); $rp = new ReflectionProperty('Exception', 'message'); var_dump($rp->getAttributes()); +$rct = new ReflectionConstant('PHP_VERSION'); +var_dump($rct->getAttributes()); + ?> --EXPECT-- array(0) { @@ -30,3 +33,5 @@ array(0) { } array(0) { } +array(0) { +} diff --git a/Zend/tests/attributes/034_target_values.phpt b/Zend/tests/attributes/034_target_values.phpt new file mode 100644 index 0000000000000..e56c0c285fbd6 --- /dev/null +++ b/Zend/tests/attributes/034_target_values.phpt @@ -0,0 +1,39 @@ +--TEST-- +Attribute flags are all different, TARGET_ALL includes all targets +--FILE-- + +--EXPECT-- +Attribute::TARGET_CLASS = 1 (127 & 1 === 1) +Attribute::TARGET_FUNCTION = 2 (127 & 2 === 2) +Attribute::TARGET_METHOD = 4 (127 & 4 === 4) +Attribute::TARGET_PROPERTY = 8 (127 & 8 === 8) +Attribute::TARGET_CLASS_CONSTANT = 16 (127 & 16 === 16) +Attribute::TARGET_PARAMETER = 32 (127 & 32 === 32) +Attribute::TARGET_CONSTANT = 64 (127 & 64 === 64) +Attribute::IS_REPEATABLE = 128 (127 & 128 === 0) +int(127) +int(127) +bool(true) diff --git a/Zend/tests/attributes/constants/allow_named_parameters.phpt b/Zend/tests/attributes/constants/allow_named_parameters.phpt new file mode 100644 index 0000000000000..7b11bc3c68165 --- /dev/null +++ b/Zend/tests/attributes/constants/allow_named_parameters.phpt @@ -0,0 +1,39 @@ +--TEST-- +Verify that named parameters can be passed to attributes on constants +--FILE-- +getAttributes(); +var_dump($attribs); +var_dump($attribs[0]->getArguments()); +$attribs[0]->newInstance(); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} +array(2) { + ["second"]=> + string(3) "bar" + ["first"]=> + string(3) "foo" +} +first: foo +second: bar diff --git a/Zend/tests/attributes/constants/ast_export.phpt b/Zend/tests/attributes/constants/ast_export.phpt new file mode 100644 index 0000000000000..655fe1a9ddecb --- /dev/null +++ b/Zend/tests/attributes/constants/ast_export.phpt @@ -0,0 +1,34 @@ +--TEST-- +AST can be recreated when constants have attributes +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +#[MyAttrib] +const WITH_ATTRIBUTE = true; +#[First] +#[Second] +const WITH_UNGROUPED = true; +#[First, Second] +const WITH_GROUPED = true; +#[MyAttrib(5, param: 'example')] +const WITH_PARAMETERS = true; +echo zend_test_compile_to_ast(file_get_contents(__FILE__)); diff --git a/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt b/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt new file mode 100644 index 0000000000000..b0b88c2f6edab --- /dev/null +++ b/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt @@ -0,0 +1,11 @@ +--TEST-- +Constants listed in valid targets when used wrong (internal attribute) +--FILE-- + +--EXPECTF-- +Fatal error: Attribute "Deprecated" cannot target class (allowed targets: function, method, class constant, constant) in %s on line %d diff --git a/Zend/tests/attributes/constants/constant_listed_as_target-userland.phpt b/Zend/tests/attributes/constants/constant_listed_as_target-userland.phpt new file mode 100644 index 0000000000000..0fcdf7795bda3 --- /dev/null +++ b/Zend/tests/attributes/constants/constant_listed_as_target-userland.phpt @@ -0,0 +1,31 @@ +--TEST-- +Constants listed in valid targets when used wrong (userland attribute) +--FILE-- +getAttributes(); +var_dump($attribs); +$attribs[0]->newInstance(); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(19) "MyConstantAttribute" + } +} + +Fatal error: Uncaught Error: Attribute "MyConstantAttribute" cannot target class (allowed targets: constant) in %s:%d +Stack trace: +#0 %s(%d): ReflectionAttribute->newInstance() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/constants/constant_redefined_addition.phpt b/Zend/tests/attributes/constants/constant_redefined_addition.phpt new file mode 100644 index 0000000000000..08f9670989627 --- /dev/null +++ b/Zend/tests/attributes/constants/constant_redefined_addition.phpt @@ -0,0 +1,21 @@ +--TEST-- +If a constant is redefined, attributes remain unchanged (no attributes) +--FILE-- +getAttributes()) + +?> +--EXPECTF-- +Warning: Constant MY_CONST already defined in %s on line %d +No attributes +array(0) { +} diff --git a/Zend/tests/attributes/constants/constant_redefined_change.phpt b/Zend/tests/attributes/constants/constant_redefined_change.phpt new file mode 100644 index 0000000000000..158753ee07d84 --- /dev/null +++ b/Zend/tests/attributes/constants/constant_redefined_change.phpt @@ -0,0 +1,27 @@ +--TEST-- +If a constant is redefined, attributes remain unchanged (different attributes) +--FILE-- +getAttributes()) + +?> +--EXPECTF-- +Warning: Constant MY_CONST already defined in %s on line %d +Has attributes (1) +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} diff --git a/Zend/tests/attributes/constants/constant_redefined_removal.phpt b/Zend/tests/attributes/constants/constant_redefined_removal.phpt new file mode 100644 index 0000000000000..0b679a55985e3 --- /dev/null +++ b/Zend/tests/attributes/constants/constant_redefined_removal.phpt @@ -0,0 +1,26 @@ +--TEST-- +If a constant is redefined, attributes remain unchanged (had attributes) +--FILE-- +getAttributes()) + +?> +--EXPECTF-- +Warning: Constant MY_CONST already defined in %s on line %d +Has attributes +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} diff --git a/Zend/tests/attributes/constants/multiple_attributes_grouped.phpt b/Zend/tests/attributes/constants/multiple_attributes_grouped.phpt new file mode 100644 index 0000000000000..71736b68008d8 --- /dev/null +++ b/Zend/tests/attributes/constants/multiple_attributes_grouped.phpt @@ -0,0 +1,25 @@ +--TEST-- +Multiple attributes in a group are allowed +--FILE-- +getAttributes()); + +?> +--EXPECTF-- +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(3) "Foo" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(3) "Bar" + } +} diff --git a/Zend/tests/attributes/constants/multiple_attributes_ungrouped.phpt b/Zend/tests/attributes/constants/multiple_attributes_ungrouped.phpt new file mode 100644 index 0000000000000..2f177a9efd3f6 --- /dev/null +++ b/Zend/tests/attributes/constants/multiple_attributes_ungrouped.phpt @@ -0,0 +1,26 @@ +--TEST-- +Multiple attributes in separate groups are allowed +--FILE-- +getAttributes()); + +?> +--EXPECTF-- +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(3) "Foo" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(3) "Bar" + } +} diff --git a/Zend/tests/attributes/constants/multiple_constants_error.phpt b/Zend/tests/attributes/constants/multiple_constants_error.phpt new file mode 100644 index 0000000000000..d4258c9f4d080 --- /dev/null +++ b/Zend/tests/attributes/constants/multiple_constants_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Error trying to add attributes to multiple constants at once +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply attributes to multiple constants at once in %s on line %d diff --git a/Zend/tests/attributes/constants/must_target_const-internal.phpt b/Zend/tests/attributes/constants/must_target_const-internal.phpt new file mode 100644 index 0000000000000..cedb6c5bd161a --- /dev/null +++ b/Zend/tests/attributes/constants/must_target_const-internal.phpt @@ -0,0 +1,11 @@ +--TEST-- +Error when attribute does not target constants (internal attribute) +--FILE-- + +--EXPECTF-- +Fatal error: Attribute "Attribute" cannot target constant (allowed targets: class) in %s on line %d diff --git a/Zend/tests/attributes/constants/must_target_const-userland.phpt b/Zend/tests/attributes/constants/must_target_const-userland.phpt new file mode 100644 index 0000000000000..3799cf2142006 --- /dev/null +++ b/Zend/tests/attributes/constants/must_target_const-userland.phpt @@ -0,0 +1,31 @@ +--TEST-- +Error when attribute does not target constants (useland attribute) +--FILE-- +getAttributes(); +var_dump($attribs); +$attribs[0]->newInstance(); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(19) "MyFunctionAttribute" + } +} + +Fatal error: Uncaught Error: Attribute "MyFunctionAttribute" cannot target constant (allowed targets: function) in %s:%d +Stack trace: +#0 %s(%d): ReflectionAttribute->newInstance() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/constants/not_repeatable-internal.phpt b/Zend/tests/attributes/constants/not_repeatable-internal.phpt new file mode 100644 index 0000000000000..b3602e186f046 --- /dev/null +++ b/Zend/tests/attributes/constants/not_repeatable-internal.phpt @@ -0,0 +1,12 @@ +--TEST-- +Validation of attribute repetition (not allowed; internal attribute) +--FILE-- + +--EXPECTF-- +Fatal error: Attribute "Deprecated" must not be repeated in %s on line %d diff --git a/Zend/tests/attributes/constants/not_repeatable-userland.phpt b/Zend/tests/attributes/constants/not_repeatable-userland.phpt new file mode 100644 index 0000000000000..85c0f2dff1e8b --- /dev/null +++ b/Zend/tests/attributes/constants/not_repeatable-userland.phpt @@ -0,0 +1,36 @@ +--TEST-- +Validation of attribute repetition (not allowed; userland attribute) +--FILE-- +getAttributes(); +var_dump($attributes); +$attributes[0]->newInstance(); + +?> +--EXPECTF-- +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} + +Fatal error: Uncaught Error: Attribute "MyAttribute" must not be repeated in %s:%d +Stack trace: +#0 %s(%d): ReflectionAttribute->newInstance() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/constants/repeatable-internal.phpt b/Zend/tests/attributes/constants/repeatable-internal.phpt new file mode 100644 index 0000000000000..57cb9eaf274db --- /dev/null +++ b/Zend/tests/attributes/constants/repeatable-internal.phpt @@ -0,0 +1,16 @@ +--TEST-- +Validation of attribute repetition (is allowed; internal attribute) +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/constants/repeatable-userland.phpt b/Zend/tests/attributes/constants/repeatable-userland.phpt new file mode 100644 index 0000000000000..ce31a903dbc57 --- /dev/null +++ b/Zend/tests/attributes/constants/repeatable-userland.phpt @@ -0,0 +1,30 @@ +--TEST-- +Validation of attribute repetition (is allowed; userland attribute) +--FILE-- +getAttributes(); +var_dump($attributes); +$attributes[0]->newInstance(); + +?> +--EXPECTF-- +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} diff --git a/Zend/tests/attributes/constants/target_all_targets_const-default.phpt b/Zend/tests/attributes/constants/target_all_targets_const-default.phpt new file mode 100644 index 0000000000000..7f79a59cd65bd --- /dev/null +++ b/Zend/tests/attributes/constants/target_all_targets_const-default.phpt @@ -0,0 +1,25 @@ +--TEST-- +Attributes with TARGET_ALL (from the default) can target constants +--FILE-- +getAttributes(); +var_dump($attribs); +$attribs[0]->newInstance(); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} diff --git a/Zend/tests/attributes/constants/target_all_targets_const-explicit.phpt b/Zend/tests/attributes/constants/target_all_targets_const-explicit.phpt new file mode 100644 index 0000000000000..6daa11b9a537d --- /dev/null +++ b/Zend/tests/attributes/constants/target_all_targets_const-explicit.phpt @@ -0,0 +1,25 @@ +--TEST-- +Attributes with TARGET_ALL (from an explicit parameter) can target constants +--FILE-- +getAttributes(); +var_dump($attribs); +$attribs[0]->newInstance(); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(11) "MyAttribute" + } +} diff --git a/Zend/tests/attributes/deprecated/constants/const_messages.phpt b/Zend/tests/attributes/deprecated/constants/const_messages.phpt new file mode 100644 index 0000000000000..1cf8b11af1565 --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/const_messages.phpt @@ -0,0 +1,49 @@ +--TEST-- +#[\Deprecated]: Messages on compile time constants. +--FILE-- + +--EXPECTF-- +Deprecated: Constant DeprecatedConst1 is deprecated in %s on line %d +1 + +Deprecated: Constant DeprecatedConst2 is deprecated, use DEPRECATED_CONST_2 in %s on line %d +2 + +Deprecated: Constant DeprecatedConst3 is deprecated, use DEPRECATED_CONST_3 in %s on line %d +3 + +Deprecated: Constant DeprecatedConst4 is deprecated since 1.0, use DEPRECATED_CONST_4 in %s on line %d +4 + +Deprecated: Constant DeprecatedConst5 is deprecated since 1.0, use DEPRECATED_CONST_5 in %s on line %d +5 + +Deprecated: Constant DeprecatedConst6 is deprecated since 1.0 in %s on line %d +6 + diff --git a/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_001.phpt b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_001.phpt new file mode 100644 index 0000000000000..955174b293e20 --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +#[\Deprecated]: Using the value of a deprecated constant as the deprecation message. +--FILE-- + +--EXPECTF-- +Deprecated: Constant TEST is deprecated, from itself in %s on line %d + +Deprecated: Constant TEST2 is deprecated in %s on line %d + +Deprecated: Constant TEST3 is deprecated, from another in %s on line %d diff --git a/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt new file mode 100644 index 0000000000000..f749293d8facc --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt @@ -0,0 +1,34 @@ +--TEST-- +#[\Deprecated]: Using the value of a deprecated constant as the deprecation message with a throwing error handler. +--FILE-- +getMessage(), PHP_EOL; +} + +try { + TEST3; +} catch (ErrorException $e) { + echo "Caught: ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Caught: Constant TEST is deprecated, from itself +Caught: Constant TEST2 is deprecated diff --git a/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_003.phpt b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_003.phpt new file mode 100644 index 0000000000000..c37b57dc42176 --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_003.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Deprecated]: Using the value of a deprecated constant in a constant expression. +--FILE-- + +--EXPECTF-- +Deprecated: Constant PREFIX is deprecated, prefix in %s on line %d + +Deprecated: Constant SUFFIX is deprecated, suffix in %s on line %d +string(12) "prefixsuffix" diff --git a/Zend/tests/attributes/deprecated/constants/error_code.phpt b/Zend/tests/attributes/deprecated/constants/error_code.phpt new file mode 100644 index 0000000000000..0a8efd7f970b4 --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/error_code.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Deprecated]: Code is E_USER_DEPRECATED for constants. +--FILE-- + +--EXPECT-- +int(16384) +int(16384) +bool(true) diff --git a/Zend/tests/attributes/deprecated/constants/value_unknown_at_compile_time_001.phpt b/Zend/tests/attributes/deprecated/constants/value_unknown_at_compile_time_001.phpt new file mode 100644 index 0000000000000..a968e26673e39 --- /dev/null +++ b/Zend/tests/attributes/deprecated/constants/value_unknown_at_compile_time_001.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Deprecated]: Constant with value unknown at compile time. +--FILE-- + +--EXPECTF-- +Deprecated: Constant CONSTANT is deprecated in %s on line %d +string(8) "Prefix-%c" +bool(true) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 991d85ff39ce1..5437208694d49 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1631,11 +1631,14 @@ static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int pri smart_str_appendc(str, '}'); } -static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent) +/* Use zend_ast_export_list() unless fewer than `list->children` children should + * be exported. */ +static ZEND_COLD void zend_ast_export_list_ex(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent, int children) { + ZEND_ASSERT(children <= list->children); uint32_t i = 0; - while (i < list->children) { + while (i < children) { if (i != 0 && separator) { smart_str_appends(str, ", "); } @@ -1644,6 +1647,11 @@ static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, } } +static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent) +{ + zend_ast_export_list_ex(str, list, separator, priority, indent, list->children); +} + static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent) { uint32_t i = 0; @@ -2216,9 +2224,26 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio goto simple_list; } - case ZEND_AST_CONST_DECL: + case ZEND_AST_CONST_DECL: { + zend_ast_list *ast_list = zend_ast_get_list(ast); + /* Attributes are stored at the end of the list if present. */ + if (ast_list->child[ast_list->children - 1]->kind == ZEND_AST_ATTRIBUTE_LIST) { + zend_ast_export_attributes( + str, + ast_list->child[ast_list->children - 1], + indent, + 1 + ); + /* So that the list printing doesn't try to print the attributes, + * use zend_ast_export_list_ex() to override the number of children + * to print. */ + smart_str_appends(str, "const "); + zend_ast_export_list_ex(str, ast_list, 1, 20, indent, ast_list->children - 1); + break; + } smart_str_appends(str, "const "); goto simple_list; + } case ZEND_AST_CLASS_CONST_GROUP: if (ast->child[1]) { zend_ast_export_attributes(str, ast->child[1], indent, 1); @@ -2916,6 +2941,12 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr) case ZEND_AST_CLASS_CONST_GROUP: ast->child[1] = attr; break; + case ZEND_AST_CONST_DECL: + /* Since constants are already stored in a list, just add the attributes + * to that list instead of storing them elsewhere; + * zend_compile_const_decl() checks the kind of the list elements. */ + zend_ast_list_add(ast, attr); + break; EMPTY_SWITCH_DEFAULT_CASE() } diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index 48f79c12610f6..c3633801be83e 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -378,7 +378,8 @@ static const char *target_names[] = { "method", "property", "class constant", - "parameter" + "parameter", + "constant" }; ZEND_API zend_string *zend_get_attribute_target_names(uint32_t flags) diff --git a/Zend/zend_attributes.h b/Zend/zend_attributes.h index 468488800ebf8..eb464772c100c 100644 --- a/Zend/zend_attributes.h +++ b/Zend/zend_attributes.h @@ -28,9 +28,10 @@ #define ZEND_ATTRIBUTE_TARGET_PROPERTY (1<<3) #define ZEND_ATTRIBUTE_TARGET_CLASS_CONST (1<<4) #define ZEND_ATTRIBUTE_TARGET_PARAMETER (1<<5) -#define ZEND_ATTRIBUTE_TARGET_ALL ((1<<6) - 1) -#define ZEND_ATTRIBUTE_IS_REPEATABLE (1<<6) -#define ZEND_ATTRIBUTE_FLAGS ((1<<7) - 1) +#define ZEND_ATTRIBUTE_TARGET_CONST (1<<6) +#define ZEND_ATTRIBUTE_TARGET_ALL ((1<<7) - 1) +#define ZEND_ATTRIBUTE_IS_REPEATABLE (1<<7) +#define ZEND_ATTRIBUTE_FLAGS ((1<<8) - 1) /* Flags for zend_attribute.flags */ #define ZEND_ATTRIBUTE_PERSISTENT (1<<0) diff --git a/Zend/zend_attributes.stub.php b/Zend/zend_attributes.stub.php index 6351ccd771838..fe70de83e4d21 100644 --- a/Zend/zend_attributes.stub.php +++ b/Zend/zend_attributes.stub.php @@ -17,6 +17,8 @@ final class Attribute const int TARGET_CLASS_CONSTANT = UNKNOWN; /** @cvalue ZEND_ATTRIBUTE_TARGET_PARAMETER */ const int TARGET_PARAMETER = UNKNOWN; + /** @cvalue ZEND_ATTRIBUTE_TARGET_CONST */ + const int TARGET_CONSTANT = UNKNOWN; /** @cvalue ZEND_ATTRIBUTE_TARGET_ALL */ const int TARGET_ALL = UNKNOWN; /** @cvalue ZEND_ATTRIBUTE_IS_REPEATABLE */ @@ -75,7 +77,7 @@ public function __construct() {} /** * @strict-properties */ -#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT)] +#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT)] final class Deprecated { public readonly ?string $message; diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index aecb216291071..14afe40c01adf 100644 --- a/Zend/zend_attributes_arginfo.h +++ b/Zend/zend_attributes_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6b54bc195be211caabb395b621380681953c1f5a */ + * Stub hash: 9aee3d8f2ced376f5929048444eaa2529ff90311 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL") @@ -129,6 +129,12 @@ static zend_class_entry *register_class_Attribute(void) zend_declare_typed_class_constant(class_entry, const_TARGET_PARAMETER_name, &const_TARGET_PARAMETER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TARGET_PARAMETER_name); + zval const_TARGET_CONSTANT_value; + ZVAL_LONG(&const_TARGET_CONSTANT_value, ZEND_ATTRIBUTE_TARGET_CONST); + zend_string *const_TARGET_CONSTANT_name = zend_string_init_interned("TARGET_CONSTANT", sizeof("TARGET_CONSTANT") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_TARGET_CONSTANT_name, &const_TARGET_CONSTANT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_TARGET_CONSTANT_name); + zval const_TARGET_ALL_value; ZVAL_LONG(&const_TARGET_ALL_value, ZEND_ATTRIBUTE_TARGET_ALL); zend_string *const_TARGET_ALL_name = zend_string_init_interned("TARGET_ALL", sizeof("TARGET_ALL") - 1, 1); @@ -258,7 +264,7 @@ static zend_class_entry *register_class_Deprecated(void) zend_attribute *attribute_Attribute_class_Deprecated_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Deprecated_0, 1); zend_string_release(attribute_name_Attribute_class_Deprecated_0); zval attribute_Attribute_class_Deprecated_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_Deprecated_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST); + ZVAL_LONG(&attribute_Attribute_class_Deprecated_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST | ZEND_ATTRIBUTE_TARGET_CONST); ZVAL_COPY_VALUE(&attribute_Attribute_class_Deprecated_0->args[0].value, &attribute_Attribute_class_Deprecated_0_arg0); return class_entry; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d05e2d21ed748..0669d106f15e9 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9502,8 +9502,16 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; + zend_ast *attributes_ast = NULL; + zend_op *last_op = NULL; for (i = 0; i < list->children; ++i) { zend_ast *const_ast = list->child[i]; + if (const_ast->kind == ZEND_AST_ATTRIBUTE_LIST) { + ZEND_ASSERT(i == list->children - 1); + attributes_ast = const_ast; + continue; + } + ZEND_ASSERT(const_ast->kind == ZEND_AST_CONST_ELEM); zend_ast *name_ast = const_ast->child[0]; zend_ast **value_ast_ptr = &const_ast->child[1]; zend_string *unqualified_name = zend_ast_get_str(name_ast); @@ -9534,10 +9542,33 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */ name_node.op_type = IS_CONST; ZVAL_STR(&name_node.u.constant, name); - zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node); + last_op = zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node); zend_register_seen_symbol(name, ZEND_SYMBOL_CONST); } + if (attributes_ast == NULL) { + return; + } + /* Validate: attributes can only be applied to one constant at a time + * Since we store the AST for the attributes in the list of children, + * there should be exactly 2 children. */ + if (list->children > 2) { + zend_error_noreturn( + E_COMPILE_ERROR, + "Cannot apply attributes to multiple constants at once" + ); + } + + HashTable *attributes = NULL; + zend_compile_attributes(&attributes, list->child[1], 0, ZEND_ATTRIBUTE_TARGET_CONST, 0); + + ZEND_ASSERT(last_op != NULL); + last_op->opcode = ZEND_DECLARE_ATTRIBUTED_CONST; + znode attribs_node; + attribs_node.op_type = IS_CONST; + ZVAL_PTR(&attribs_node.u.constant, attributes); + zend_emit_op_data(&attribs_node); + CG(active_op_array)->fn_flags |= ZEND_ACC_PTR_OPS; } /* }}}*/ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index aec72743f6ca9..62d0fbcded2ee 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -395,6 +395,11 @@ typedef struct _zend_oparray_context { /* has #[\Override] attribute | | | */ #define ZEND_ACC_OVERRIDE (1 << 28) /* | X | | */ /* | | | */ +/* Has IS_PTR operands that needs special cleaning; same | | | */ +/* value as ZEND_ACC_OVERRIDE but override is for class | | | */ +/* methods and this is for the top level op array | | | */ +#define ZEND_ACC_PTR_OPS (1 << 28) /* | X | | */ +/* | | | */ /* has #[\NoDiscard] attribute | | | */ #define ZEND_ACC_NODISCARD (1 << 29) /* | X | | */ /* | | | */ diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index f29466cfe2c9c..28a4b7b048cf0 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -18,6 +18,7 @@ */ #include "zend.h" +#include "zend_attributes.h" #include "zend_constants.h" #include "zend_exceptions.h" #include "zend_execute.h" @@ -49,6 +50,9 @@ void free_zend_constant(zval *zv) if (c->filename) { zend_string_release_ex(c->filename, 0); } + if (c->attributes) { + zend_hash_release(c->attributes); + } efree(c); } else { zval_internal_ptr_dtor(&c->value); @@ -58,6 +62,9 @@ void free_zend_constant(zval *zv) if (c->filename) { zend_string_release_ex(c->filename, 1); } + if (c->attributes) { + zend_hash_release(c->attributes); + } free(c); } } @@ -77,6 +84,9 @@ static void copy_zend_constant(zval *zv) if (c->filename != NULL) { c->filename = zend_string_copy(c->filename); } + if (c->attributes != NULL) { + c->attributes = zend_array_dup(c->attributes); + } if (Z_TYPE(c->value) == IS_STRING) { Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1); } @@ -467,7 +477,11 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, } if (!(flags & ZEND_FETCH_CLASS_SILENT) && (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED)) { - zend_error(E_DEPRECATED, "Constant %s is deprecated", name); + if (!CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); + zend_deprecated_constant(c, c->name); + CONST_UNPROTECT_RECURSION(c); + } } return &c->value; } @@ -514,6 +528,8 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) } } + c->attributes = NULL; + /* Check if the user is trying to define any special constant */ if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) @@ -535,3 +551,22 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) } return ret; } + +void zend_constant_add_attributes(zend_constant *c, HashTable *attributes) { + GC_TRY_ADDREF(attributes); + c->attributes = attributes; + + zend_attribute *deprecated_attribute = zend_get_attribute_str( + c->attributes, + "deprecated", + strlen("deprecated") + ); + + if (deprecated_attribute) { + ZEND_CONSTANT_SET_FLAGS( + c, + ZEND_CONSTANT_FLAGS(c) | CONST_DEPRECATED, + ZEND_CONSTANT_MODULE_NUMBER(c) + ); + } +} diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index 4a4da46bfc9b1..3912215d80775 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -45,6 +45,7 @@ typedef struct _zend_constant { zval value; zend_string *name; zend_string *filename; + HashTable *attributes; } zend_constant; #define ZEND_CONSTANT_FLAGS(c) \ @@ -97,6 +98,7 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number); ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number); ZEND_API zend_result zend_register_constant(zend_constant *c); +void zend_constant_add_attributes(zend_constant *c, HashTable *attributes); #ifdef ZTS void zend_copy_constants(HashTable *target, HashTable *source); #endif diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 89fbcf2cbd781..0fbfdfa07ef04 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1979,6 +1979,24 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_ zend_string_release(message_suffix); } +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name) +{ + zend_string *message_suffix = ZSTR_EMPTY_ALLOC(); + + if (get_deprecation_suffix_from_attribute(c->attributes, NULL, &message_suffix) == FAILURE) { + return; + } + + int code = ZEND_CONSTANT_MODULE_NUMBER(c) == PHP_USER_CONSTANT ? E_USER_DEPRECATED : E_DEPRECATED; + + zend_error_unchecked(code, "Constant %s is deprecated%S", + ZSTR_VAL(constant_name), + message_suffix + ); + + zend_string_release(message_suffix); +} + ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void) { zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated"); @@ -5322,7 +5340,11 @@ static zend_always_inline zend_result _zend_quick_get_constant( if (!check_defined_only) { ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) { - zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(c->name)); + if (!CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); + zend_deprecated_constant(c, c->name); + CONST_UNPROTECT_RECURSION(c); + } return SUCCESS; } } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index b9fef311d9f9b..cf15c9e3b2db5 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -25,6 +25,7 @@ #include "zend_hash.h" #include "zend_operators.h" #include "zend_variables.h" +#include "zend_constants.h" #include @@ -64,6 +65,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(const zend_execute_ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void); ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 12df2a9ee5b99..9a7803e44e66e 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -300,6 +300,9 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) if (c->filename) { zend_string_release_ex(c->filename, 0); } + if (c->attributes) { + zend_hash_release(c->attributes); + } efree(c); zend_string_release_ex(key, 0); } ZEND_HASH_MAP_FOREACH_END_DEL(); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 190292fada760..0c5bb36501e72 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -391,6 +391,7 @@ attributed_statement: | trait_declaration_statement { $$ = $1; } | interface_declaration_statement { $$ = $1; } | enum_declaration_statement { $$ = $1; } + | T_CONST const_list ';' { $$ = $2; } ; top_statement: @@ -414,7 +415,6 @@ top_statement: | T_USE use_type group_use_declaration ';' { $$ = $3; $$->attr = $2; } | T_USE use_declarations ';' { $$ = $2; $$->attr = ZEND_SYMBOL_CLASS; } | T_USE use_type use_declarations ';' { $$ = $3; $$->attr = $2; } - | T_CONST const_list ';' { $$ = $2; } ; use_type: diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index b25152ec1248b..6e7d31e15a40f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -580,6 +580,18 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) efree(op_array->vars); } + /* ZEND_ACC_PTR_OPS and ZEND_ACC_OVERRIDE use the same value */ + if ((op_array->fn_flags & ZEND_ACC_PTR_OPS) && !op_array->function_name) { + zend_op *op = op_array->opcodes; + zend_op *end = op + op_array->last; + while (op < end) { + if (op->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) { + HashTable *attributes = Z_PTR_P(RT_CONSTANT(op+1, (op+1)->op1)); + zend_hash_release(attributes); + } + op++; + } + } if (op_array->literals) { zval *literal = op_array->literals; zval *end = literal + op_array->last_literal; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7b861688c9661..9c2ba0038b4a4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8261,6 +8261,49 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST) +{ + USE_OPLINE + zval *name; + zval *val; + zend_constant c; + + SAVE_OPLINE(); + name = GET_OP1_ZVAL_PTR(BP_VAR_R); + val = GET_OP2_ZVAL_PTR(BP_VAR_R); + + ZVAL_COPY(&c.value, val); + if (Z_OPT_CONSTANT(c.value)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { + zval_ptr_dtor_nogc(&c.value); + FREE_OP1(); + FREE_OP2(); + HANDLE_EXCEPTION(); + } + } + /* non persistent, case sensitive */ + ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); + c.name = zend_string_copy(Z_STR_P(name)); + + if (zend_register_constant(&c) == FAILURE) { + FREE_OP1(); + FREE_OP2(); + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R)); + zend_constant *registered = zend_get_constant_ptr(c.name); + ZEND_ASSERT(attributes != NULL); + ZEND_ASSERT(registered != NULL); + zend_constant_add_attributes(registered, attributes); + + FREE_OP1(); + FREE_OP2(); + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2211f6753485d..226e0446abbd1 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -8042,6 +8042,48 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *name; + zval *val; + zend_constant c; + + SAVE_OPLINE(); + name = RT_CONSTANT(opline, opline->op1); + val = RT_CONSTANT(opline, opline->op2); + + ZVAL_COPY(&c.value, val); + if (Z_OPT_CONSTANT(c.value)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { + zval_ptr_dtor_nogc(&c.value); + + + HANDLE_EXCEPTION(); + } + } + /* non persistent, case sensitive */ + ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); + c.name = zend_string_copy(Z_STR_P(name)); + + if (zend_register_constant(&c) == FAILURE) { + + + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + HashTable *attributes = Z_PTR_P(get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)); + zend_constant *registered = zend_get_constant_ptr(c.name); + ZEND_ASSERT(attributes != NULL); + ZEND_ASSERT(registered != NULL); + zend_constant_add_attributes(registered, attributes); + + + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -57569,6 +57611,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_LABEL, (void*)&&ZEND_JMP_FRAMELESS_SPEC_CONST_LABEL, (void*)&&ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_LABEL, + (void*)&&ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_INIT_FCALL_OFFSET_SPEC_CONST_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -59543,6 +59586,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_DECLARE_CONST_SPEC_CONST_CONST) HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST): + VM_TRACE(ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST) + ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST) + HYBRID_BREAK(); HYBRID_CASE(ZEND_YIELD_SPEC_CONST_CONST): VM_TRACE(ZEND_YIELD_SPEC_CONST_CONST) ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -66755,6 +66803,7 @@ void zend_vm_init(void) ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_HANDLER, ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER, + ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER, ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_NULL_HANDLER, @@ -67712,7 +67761,7 @@ void zend_vm_init(void) 1255, 1256 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1, - 3486, + 3487, 1266 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1, 1276 | SPEC_RULE_OP2, @@ -67746,7 +67795,7 @@ void zend_vm_init(void) 1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1584 | SPEC_RULE_OP1, 1589, - 3486, + 3487, 1590 | SPEC_RULE_OP1, 1595 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1620 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -67877,52 +67926,52 @@ void zend_vm_init(void) 2573 | SPEC_RULE_OBSERVER, 2575, 2576, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, - 3486, + 2577, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, + 3487, }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -68095,7 +68144,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2585 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2586 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68103,7 +68152,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2610 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2611 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68111,7 +68160,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2635 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2636 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -68122,17 +68171,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2660 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2661 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2685 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2686 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2710 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2711 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -68143,17 +68192,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2735 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2736 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2760 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2761 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2785 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2786 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -68164,14 +68213,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2811 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2886 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3110 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3111 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -68182,14 +68231,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2961 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3036 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3115 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3116 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -68200,12 +68249,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2811 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2886 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -68216,12 +68265,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2961 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3036 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -68229,12 +68278,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3120 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3121 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3195 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3196 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -68242,79 +68291,79 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3270 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3271 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3345 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3346 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3432 | SPEC_RULE_OP1; + spec = 3433 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3437 | SPEC_RULE_OP1; + spec = 3438 | SPEC_RULE_OP1; } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { - spec = 3442 | SPEC_RULE_OP1; + spec = 3443 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3420 | SPEC_RULE_RETVAL; + spec = 3421 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3422 | SPEC_RULE_RETVAL; + spec = 3423 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3424 | SPEC_RULE_RETVAL; + spec = 3425 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3426 | SPEC_RULE_RETVAL; + spec = 3427 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3428; - } else if (op1_info == MAY_BE_LONG) { spec = 3429; + } else if (op1_info == MAY_BE_LONG) { + spec = 3430; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3430; - } else if (op1_info == MAY_BE_LONG) { spec = 3431; + } else if (op1_info == MAY_BE_LONG) { + spec = 3432; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2584; + spec = 2585; } break; case ZEND_INIT_FCALL: if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) { - spec = 2577; + spec = 2578; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2578; + spec = 2579; } break; case ZEND_SEND_VAL: if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3482; + spec = 3483; } break; case ZEND_SEND_VAR_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3477 | SPEC_RULE_OP1; + spec = 3478 | SPEC_RULE_OP1; } break; case ZEND_FE_FETCH_R: if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 3484 | SPEC_RULE_RETVAL; + spec = 3485 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -68322,22 +68371,22 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3447 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3448 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_SEND_VAL_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3483; + spec = 3484; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3472 | SPEC_RULE_OP1; + spec = 3473 | SPEC_RULE_OP1; } break; case ZEND_COUNT: if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 2579 | SPEC_RULE_OP1; + spec = 2580 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 7f3a3cb5de260..cbbc6a4772788 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1372,502 +1372,503 @@ _(2574, ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER) \ _(2575, ZEND_JMP_FRAMELESS_SPEC_CONST) \ _(2576, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED) \ - _(2577, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ - _(2578, ZEND_RECV_NOTYPE_SPEC) \ - _(2580, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2577, ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST) \ + _(2578, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \ + _(2579, ZEND_RECV_NOTYPE_SPEC) \ _(2581, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ - _(2583, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ - _(2584, ZEND_JMP_FORWARD_SPEC) \ - _(2590, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2582, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2584, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ + _(2585, ZEND_JMP_FORWARD_SPEC) \ + _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2592, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2594, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2595, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2596, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2593, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2595, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2596, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2597, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2599, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2605, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2606, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2598, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2600, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2606, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2607, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2609, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2615, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2608, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2610, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2617, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2619, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2620, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2621, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2618, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2620, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2621, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2622, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2624, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2630, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2631, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2623, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2625, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2631, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2632, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2634, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2640, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2633, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2635, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2642, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2644, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2645, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2646, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2643, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2645, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2646, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2647, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2649, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2655, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2656, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2648, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2650, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2656, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2657, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2659, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2661, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2658, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2660, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2662, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2664, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2663, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2667, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2669, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2670, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2671, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2668, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2670, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2671, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2672, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2674, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2680, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2681, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2673, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2675, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2681, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2682, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2684, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2686, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2683, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2685, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2687, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2689, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2690, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2688, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2690, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2692, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2694, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2695, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2696, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2693, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2695, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2696, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2697, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2699, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2705, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2706, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2698, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2700, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2706, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2707, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2709, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2711, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2708, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2710, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2712, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2714, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2715, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2713, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2715, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2717, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2719, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2720, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2721, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2718, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2720, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2721, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2722, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2724, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2730, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2731, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2723, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2725, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2731, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2732, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2734, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2740, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2733, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2735, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2742, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2744, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2745, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2746, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2743, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2745, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2746, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2747, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2749, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2755, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2756, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2748, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2750, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2756, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2757, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2759, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2765, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2758, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2760, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2767, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2769, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2770, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2771, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2768, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2770, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2771, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2772, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2774, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2780, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2781, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2773, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2775, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2781, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2782, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2784, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2790, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2783, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2785, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2792, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2794, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2795, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2796, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2793, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2795, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2796, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2797, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2799, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2805, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2806, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2798, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2800, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2806, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2807, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2809, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2825, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2852, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2870, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2871, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2874, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2875, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2876, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2877, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2878, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2882, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2883, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2884, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2900, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2927, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2945, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2946, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2949, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2950, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2951, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2952, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2953, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2957, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2958, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2959, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2975, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3002, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3020, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3021, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3024, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3025, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3026, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3027, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3028, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3032, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3033, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3034, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3050, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3077, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3095, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3096, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3099, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3100, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3101, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3102, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3103, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3107, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3108, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3109, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3110, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3114, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3115, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3119, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3123, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3124, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3125, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3126, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3127, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3128, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3132, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3133, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3134, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3135, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3162, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3163, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3164, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3180, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3184, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3185, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3186, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3187, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3188, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3192, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3193, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3194, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3209, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3237, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3238, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3239, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3255, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3259, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3260, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3261, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3262, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3263, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3267, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3268, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3269, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3284, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3312, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3313, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3314, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3330, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3334, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3335, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3336, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3337, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3342, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3343, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3344, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3359, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3387, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3388, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3389, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3405, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3409, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3410, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3411, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3412, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3413, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3417, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3418, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3419, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3420, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3421, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3422, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3423, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3424, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3425, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3426, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3427, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3428, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3429, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3430, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3431, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3432, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3433, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(2808, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2810, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2849, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2853, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2854, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2855, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2871, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2874, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2875, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2876, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2877, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2878, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2879, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2883, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2884, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2885, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2924, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2928, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2929, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2930, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2946, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2949, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2950, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2951, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2952, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2953, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2954, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2958, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2959, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2960, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2999, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3003, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3004, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3005, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3021, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3024, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3025, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3026, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3027, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3028, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3029, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3033, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3034, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3035, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3074, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3078, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3079, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3080, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3096, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3099, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3100, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3101, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3102, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3103, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3104, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3108, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3109, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3110, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3111, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3115, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3116, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3120, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3124, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3125, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3126, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3128, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3129, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3133, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3134, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3135, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3159, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3163, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3164, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3165, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3184, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3185, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3186, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3187, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3188, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3189, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3193, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3194, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3195, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3209, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3234, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3238, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3239, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3240, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3259, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3260, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3261, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3262, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3263, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3264, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3268, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3269, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3270, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3284, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3309, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3313, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3314, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3315, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3334, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3335, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3336, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3338, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3339, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3343, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3344, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3345, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3359, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3384, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3388, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3389, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3390, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3409, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3410, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3411, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3412, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3413, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3414, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3418, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3419, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3420, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3421, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3422, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3423, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3424, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3425, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3426, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3427, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3428, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3429, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3430, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3431, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3432, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3433, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ _(3434, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3436, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3437, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3438, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3435, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3437, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3438, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ _(3439, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3441, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3442, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3443, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3440, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3442, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3443, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ _(3444, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3446, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3448, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3445, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3447, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ _(3449, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3451, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3452, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3453, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3450, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3452, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3453, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3454, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3456, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3455, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3459, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3461, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3467, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3468, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3460, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3462, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3468, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ _(3469, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3471, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3474, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3476, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3479, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3481, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3482, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3483, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3484, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3485, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3485+1, ZEND_NULL) + _(3470, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3472, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3475, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3477, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3480, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3482, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3483, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3484, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3485, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3486, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3486+1, ZEND_NULL) diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index d7d4d9e770b5b..00ad38baaafeb 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -22,7 +22,7 @@ #include #include -static const char *zend_vm_opcodes_names[210] = { +static const char *zend_vm_opcodes_names[211] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -233,9 +233,10 @@ static const char *zend_vm_opcodes_names[210] = { "ZEND_FRAMELESS_ICALL_3", "ZEND_JMP_FRAMELESS", "ZEND_INIT_PARENT_PROPERTY_HOOK_CALL", + "ZEND_DECLARE_ATTRIBUTED_CONST", }; -static uint32_t zend_vm_opcodes_flags[210] = { +static uint32_t zend_vm_opcodes_flags[211] = { 0x00000000, 0x00000b0b, 0x00000b0b, @@ -446,6 +447,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000000, 0x01042003, 0x01001103, + 0x00000303, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index e15b1a19d5cdb..29469bb5f7dca 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -293,7 +293,8 @@ END_EXTERN_C() #define ZEND_FRAMELESS_ICALL_3 207 #define ZEND_JMP_FRAMELESS 208 #define ZEND_INIT_PARENT_PROPERTY_HOOK_CALL 209 +#define ZEND_DECLARE_ATTRIBUTED_CONST 210 -#define ZEND_VM_LAST_OPCODE 209 +#define ZEND_VM_LAST_OPCODE 210 #endif diff --git a/docs/source/core/data-structures/zend_constant.rst b/docs/source/core/data-structures/zend_constant.rst index a4245d6e3c13f..a5e85dc78638c 100644 --- a/docs/source/core/data-structures/zend_constant.rst +++ b/docs/source/core/data-structures/zend_constant.rst @@ -15,10 +15,12 @@ PHP constants (referring to non-class constants) are stored in a dedicated struc zval value; zend_string *name; zend_string *filename; + HashTable *attributes; } zend_constant; The ``value`` field stores both the value itself and some metadata. The ``name`` and ``filename`` -store the name of the constant and the name of the file in which it was defined. +store the name of the constant and the name of the file in which it was defined. The ``attributes`` +field stores the attributes applied to the constant. ******* value @@ -59,6 +61,15 @@ constants that have already been defined. This string is released when the const filename ********** -Finally, the ``filename`` holds another ``zend_string`` with the name of the file in which the -constant was defined, or ``NULL`` if not defined userland code. This field provides the foundation -for the PHP method ``ReflectionConstant::getFileName()``. +The ``filename`` holds another ``zend_string`` with the name of the file in which the constant was +defined, or ``NULL`` if not defined userland code. This field provides the foundation for the PHP +method ``ReflectionConstant::getFileName()``. + +************ + attributes +************ + +The ``attributes`` holds a ``HashTable`` (essentially an array) with the details of the attributes +that were applied to the constant. Note that attributes can only be added to constants declared at +compile time via ``const``, e.g. ``const EXAMPLE = 123``, not those declared at runtime, e.g. +``define( 'EXAMPLE', 123 );``. diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index a2c3c7fa0fbb4..f3011dff99dd6 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -600,6 +600,7 @@ static zend_always_inline int zend_jit_trace_op_len(const zend_op *opline) case ZEND_ASSIGN_OBJ_REF: case ZEND_ASSIGN_STATIC_PROP_REF: case ZEND_FRAMELESS_ICALL_3: + case ZEND_DECLARE_ATTRIBUTED_CONST: return 2; /* OP_DATA */ case ZEND_RECV_INIT: len = 1; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 0ce7f082ae15f..d39a5c44be8bd 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -375,9 +375,13 @@ static zend_always_inline zend_constant* _zend_quick_get_constant( if (!check_defined_only) { if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) { - zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(c->name)); - if (EG(exception)) { - return NULL; + if (!CONST_IS_RECURSIVE(c)) { + CONST_PROTECT_RECURSION(c); + zend_deprecated_constant(c, c->name); + CONST_UNPROTECT_RECURSION(c); + if (EG(exception)) { + return NULL; + } } return c; } diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index d2b714d937dac..fee90e42b574f 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -251,6 +251,13 @@ static void zend_file_cache_unserialize_func(zval *zv, zend_persistent_script *script, void *buf); +static void zend_file_cache_serialize_attribute(zval *zv, + zend_persistent_script *script, + zend_file_cache_metainfo *info, + void *buf); + +static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_script *script, void *buf); + static void *zend_file_cache_serialize_interned(zend_string *str, zend_file_cache_metainfo *info) { @@ -431,6 +438,9 @@ static void zend_file_cache_serialize_zval(zval *zv, /* Used by static properties. */ SERIALIZE_PTR(Z_INDIRECT_P(zv)); break; + case IS_PTR: + /* Used by attributes on constants, will be handled separately */ + break; default: ZEND_ASSERT(Z_TYPE_P(zv) < IS_STRING); break; @@ -549,6 +559,13 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra UNSERIALIZE_PTR(opline); end = opline + op_array->last; while (opline < end) { + if (opline->opcode == ZEND_OP_DATA + && (opline-1)->opcode == ZEND_DECLARE_ATTRIBUTED_CONST + ) { + zval *literal = RT_CONSTANT(opline, opline->op1); + SERIALIZE_ATTRIBUTES(Z_PTR_P(literal)); + } + #if ZEND_USE_ABS_CONST_ADDR if (opline->op1_type == IS_CONST) { SERIALIZE_PTR(opline->op1.zv); @@ -1316,6 +1333,9 @@ static void zend_file_cache_unserialize_zval(zval *zv, /* Used by static properties. */ UNSERIALIZE_PTR(Z_INDIRECT_P(zv)); break; + case IS_PTR: + /* Used by attributes on constants, will be handled separately */ + break; default: ZEND_ASSERT(Z_TYPE_P(zv) < IS_STRING); break; @@ -1485,6 +1505,13 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr break; } #endif + + if (opline->opcode == ZEND_OP_DATA + && (opline-1)->opcode == ZEND_DECLARE_ATTRIBUTED_CONST + ) { + zval *literal = RT_CONSTANT(opline, opline->op1); + UNSERIALIZE_ATTRIBUTES(Z_PTR_P(literal)); + } zend_deserialize_opcode_handler(opline); opline++; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a384cdd2b9a06..202cd73c90422 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -280,6 +280,8 @@ static void zend_persist_zval(zval *z) efree(old_ref); } break; + case IS_PTR: + break; default: ZEND_ASSERT(Z_TYPE_P(z) < IS_STRING); break; @@ -612,6 +614,12 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } } #endif + if (opline->opcode == ZEND_OP_DATA && (opline-1)->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) { + zval *literal = RT_CONSTANT(opline, opline->op1); + HashTable *attributes = Z_PTR_P(literal); + attributes = zend_persist_attributes(attributes); + ZVAL_PTR(literal, attributes); + } } efree(op_array->opcodes); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 42a6cf76d62da..639d7d5446705 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -157,6 +157,8 @@ static void zend_persist_zval_calc(zval *z) } } break; + case IS_PTR: + break; default: ZEND_ASSERT(Z_TYPE_P(z) < IS_STRING); break; @@ -264,6 +266,19 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes); ADD_SIZE(sizeof(zend_op) * op_array->last); + /* ZEND_ACC_PTR_OPS and ZEND_ACC_OVERRIDE use the same value */ + if ((op_array->fn_flags & ZEND_ACC_PTR_OPS) && !op_array->function_name) { + zend_op *op = op_array->opcodes; + zend_op *end = op + op_array->last; + while (op < end) { + if (op->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) { + HashTable *attributes = Z_PTR_P(RT_CONSTANT(op+1, (op+1)->op1)); + zend_persist_attributes_calc(attributes); + } + op++; + } + } + if (op_array->filename) { ADD_STRING(op_array->filename); } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index bff617cfb61de..8ef0269481cf7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -7813,6 +7813,18 @@ ZEND_METHOD(ReflectionConstant, getExtensionName) } /* }}} */ +ZEND_METHOD(ReflectionConstant, getAttributes) +{ + reflection_object *intern; + zend_constant *const_; + + GET_REFLECTION_OBJECT_PTR(const_); + + reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU, + const_->attributes, 0, NULL, ZEND_ATTRIBUTE_TARGET_CONST, + const_->filename); +} + ZEND_METHOD(ReflectionConstant, __toString) { reflection_object *intern; diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index be511d7ee14cd..63518b446ad86 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -923,4 +923,6 @@ public function getExtension(): ?ReflectionExtension {} public function getExtensionName(): string|false {} public function __toString(): string {} + + public function getAttributes(?string $name = null, int $flags = 0): array {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index d78a685dde9c9..d50dc04ae3d15 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3c6be99bb36965139464925a618cb0bf03affa62 */ + * Stub hash: 7a8d126a96f0115783bd20a9adfc6bdc5ee88fda */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -719,6 +719,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionConstant___toString arginfo_class_ReflectionFunction___toString +#define arginfo_class_ReflectionConstant_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes + ZEND_METHOD(Reflection, getModifierNames); ZEND_METHOD(ReflectionClass, __clone); ZEND_METHOD(ReflectionFunctionAbstract, inNamespace); @@ -987,6 +989,7 @@ ZEND_METHOD(ReflectionConstant, getFileName); ZEND_METHOD(ReflectionConstant, getExtension); ZEND_METHOD(ReflectionConstant, getExtensionName); ZEND_METHOD(ReflectionConstant, __toString); +ZEND_METHOD(ReflectionConstant, getAttributes); static const zend_function_entry class_Reflection_methods[] = { ZEND_ME(Reflection, getModifierNames, arginfo_class_Reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -1355,6 +1358,7 @@ static const zend_function_entry class_ReflectionConstant_methods[] = { ZEND_ME(ReflectionConstant, getExtension, arginfo_class_ReflectionConstant_getExtension, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, getExtensionName, arginfo_class_ReflectionConstant_getExtensionName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, __toString, arginfo_class_ReflectionConstant___toString, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionConstant, getAttributes, arginfo_class_ReflectionConstant_getAttributes, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/reflection/tests/ReflectionConstant_getAttributes.phpt b/ext/reflection/tests/ReflectionConstant_getAttributes.phpt new file mode 100644 index 0000000000000..438b5ba57a7c1 --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getAttributes.phpt @@ -0,0 +1,19 @@ +--TEST-- +ReflectionConstant::getAttributes() with attribute +--FILE-- +getAttributes()); + +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(3) "Foo" + } +} diff --git a/ext/reflection/tests/ReflectionConstant_getAttributes_empty.phpt b/ext/reflection/tests/ReflectionConstant_getAttributes_empty.phpt new file mode 100644 index 0000000000000..25aa1000de84d --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getAttributes_empty.phpt @@ -0,0 +1,24 @@ +--TEST-- +ReflectionConstant::getAttributes() when there are none +--FILE-- +getAttributes()); + +define('RT_CONST', 42); +$reflectionConstant = new ReflectionConstant('RT_CONST'); +var_dump($reflectionConstant->getAttributes()); + +const CT_CONST = 43; +$reflectionConstant = new ReflectionConstant('CT_CONST'); +var_dump($reflectionConstant->getAttributes()); + +?> +--EXPECT-- +array(0) { +} +array(0) { +} +array(0) { +} diff --git a/ext/reflection/tests/ReflectionConstant_isDeprecated_userland.phpt b/ext/reflection/tests/ReflectionConstant_isDeprecated_userland.phpt new file mode 100644 index 0000000000000..f5ed056a6bc56 --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_isDeprecated_userland.phpt @@ -0,0 +1,13 @@ +--TEST-- +ReflectionConstant::isDeprecated() from attribute +--FILE-- +isDeprecated()); + +?> +--EXPECT-- +bool(true) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index ba18639aead82..403217e926136 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -1591,3 +1591,22 @@ static PHP_FUNCTION(zend_test_create_throwing_resource) zend_resource *res = zend_register_resource(NULL, le_throwing_resource); ZVAL_RES(return_value, res); } + +static PHP_FUNCTION(zend_test_compile_to_ast) +{ + zend_string *str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str) + ZEND_PARSE_PARAMETERS_END(); + + zend_arena *ast_arena; + zend_ast *ast = zend_compile_string_to_ast(str, &ast_arena, ZSTR_EMPTY_ALLOC()); + + zend_string *result = zend_ast_export("", ast, ""); + + zend_ast_destroy(ast); + zend_arena_destroy(ast_arena); + + RETVAL_STR(result); +} diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 10272c51cad49..d75e160db9782 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -319,6 +319,8 @@ function zend_test_cast_fread($stream): void {} function zend_test_is_zend_ptr(int $addr): bool {} function zend_test_log_err_debug(string $str): void {} + + function zend_test_compile_to_ast(string $str): string {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 62b57223dac2a..14a634f197d46 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: bedc3883fbfe2491c95375beb13140e7fcfd83a5 */ + * Stub hash: 8022d3e8b34d0ebd71f1be19eeb720947bea67ed */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -175,6 +175,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_log_err_debug, 0, 1, I ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) ZEND_END_ARG_INFO() +#define arginfo_zend_test_compile_to_ast arginfo_zend_create_unterminated_string + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -312,6 +314,7 @@ static ZEND_FUNCTION(zend_test_set_fmode); static ZEND_FUNCTION(zend_test_cast_fread); static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(zend_test_log_err_debug); +static ZEND_FUNCTION(zend_test_compile_to_ast); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -428,6 +431,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread) ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug) + ZEND_FE(zend_test_compile_to_ast, arginfo_zend_test_compile_to_ast) #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY(ZEND_NS_NAME("ZendTestNS2", "namespaced_func"), zif_ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func, 0, NULL, NULL) #else diff --git a/ext/zend_test/tests/compile_to_ast/basic_ast.phpt b/ext/zend_test/tests/compile_to_ast/basic_ast.phpt new file mode 100644 index 0000000000000..f4e0043560ec8 --- /dev/null +++ b/ext/zend_test/tests/compile_to_ast/basic_ast.phpt @@ -0,0 +1,54 @@ +--TEST-- +AST can be recreated (basic example) +--EXTENSIONS-- +zend_test +--FILE-- +value = $v; + } + + public function getValue(): int { + return $this->value; + } +} + +echo zend_test_compile_to_ast( file_get_contents( __FILE__ ) ); + +?> +--EXPECT-- +#[MyAttrib] +function doSomething(int $intParam, string $stringParam): object { + return (object)[$intParam, $stringParam]; +} + +const MY_CONSTANT = true; +class Example { + private int $value; + public function __construct(int $v) { + $this->value = $v; + } + + public function getValue(): int { + return $this->value; + } + +} + +echo zend_test_compile_to_ast(file_get_contents(__FILE__)); diff --git a/ext/zend_test/tests/compile_to_ast/complicated_class.phpt b/ext/zend_test/tests/compile_to_ast/complicated_class.phpt new file mode 100644 index 0000000000000..8ea31296d031d --- /dev/null +++ b/ext/zend_test/tests/compile_to_ast/complicated_class.phpt @@ -0,0 +1,89 @@ +--TEST-- +AST can be recreated (complicated class example) +--EXTENSIONS-- +zend_test +--FILE-- + $this->alwaysLowerCase; + set => strtolower( $value ); + } + + public readonly bool $negated; + + public const CONST_PUBLIC = 1; + protected const CONST_PROTECTED = "abc"; + private const CONST_PRIVATE = [ 1, 2 ]; + + public static ?object $cache = null; + + public function __construct( public bool $boolVal ) { + $this->negated = !$boolVal; + } + + public function setValue( string $value ): void { + $this->alwaysLowerCase = $value; + } + + public static function getPrivateConst(): array { + return self::CONST_PRIVATE; + } +} + +echo zend_test_compile_to_ast( file_get_contents( __FILE__ ) ); + +?> +--EXPECT-- +interface MyInterface1 { +} + +interface MyInterface2 implements MyInterface1 { +} + +abstract class MyBaseClass implements MyInterface2 { + public final function get5(): int { + return 5; + } + + public abstract function setValue(string $value): void; + +} + +class MySubClass extends MyBaseClass { + public private(set) string $alwaysLowerCase = 'STARTS UPPER' { + get => $this->alwaysLowerCase; + set => strtolower($value); + } + public readonly bool $negated; + public const CONST_PUBLIC = 1; + protected const CONST_PROTECTED = 'abc'; + private const CONST_PRIVATE = [1, 2]; + public static ?object $cache = null; + public function __construct(public bool $boolVal) { + $this->negated = !$boolVal; + } + + public function setValue(string $value): void { + $this->alwaysLowerCase = $value; + } + + public static function getPrivateConst(): array { + return self::CONST_PRIVATE; + } + +} + +echo zend_test_compile_to_ast(file_get_contents(__FILE__)); diff --git a/ext/zend_test/tests/compile_to_ast/enum.phpt b/ext/zend_test/tests/compile_to_ast/enum.phpt new file mode 100644 index 0000000000000..45c05ee7672a7 --- /dev/null +++ b/ext/zend_test/tests/compile_to_ast/enum.phpt @@ -0,0 +1,54 @@ +--TEST-- +AST can be recreated (enums) +--EXTENSIONS-- +zend_test +--FILE-- + false, + MyBoolean::MyTrue => true, + }; + } +} + +echo zend_test_compile_to_ast( file_get_contents( __FILE__ ) ); + +?> +--EXPECT-- +enum Suit { + case Hearts; + case Diamonds; + case Clubs; + case Spades; + public const Clubz = self::Clubs; +} + +enum MyBoolean: int { + case MyFalse = 0; + case MyTrue = 1; + public function toBool(): bool { + return match ($this) { + MyBoolean::MyFalse => false, + MyBoolean::MyTrue => true, + }; + } + +} + +echo zend_test_compile_to_ast(file_get_contents(__FILE__)); diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 5d7a1c0af78c0..df64dcaebea2c 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -429,7 +429,8 @@ PHP_FUNCTION(phpdbg_start_oplog) static zend_always_inline bool phpdbg_is_ignored_opcode(uint8_t opcode) { return opcode == ZEND_NOP || opcode == ZEND_OP_DATA || opcode == ZEND_FE_FREE || opcode == ZEND_FREE || opcode == ZEND_ASSERT_CHECK || opcode == ZEND_VERIFY_RETURN_TYPE - || opcode == ZEND_DECLARE_CONST || opcode == ZEND_DECLARE_CLASS || opcode == ZEND_DECLARE_FUNCTION + || opcode == ZEND_DECLARE_CONST || opcode == ZEND_DECLARE_ATTRIBUTED_CONST + || opcode == ZEND_DECLARE_CLASS || opcode == ZEND_DECLARE_FUNCTION || opcode == ZEND_DECLARE_CLASS_DELAYED || opcode == ZEND_DECLARE_ANON_CLASS || opcode == ZEND_FAST_RET || opcode == ZEND_TICKS || opcode == ZEND_EXT_STMT || opcode == ZEND_EXT_FCALL_BEGIN || opcode == ZEND_EXT_FCALL_END From 272abc2fb70cfa950229e31fa1a0d8fc2ce2b9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 29 Apr 2025 21:39:12 +0200 Subject: [PATCH 435/503] Optimize `match(true)` (#18423) * Optimizer: Optimize `IS_IDENTICAL` with true/false/null to `TYPE_CHECK` This optimization is already happening in the compiler for explicit `===` expressions, but not for `match()`, which also compiles to `IS_IDENTICAL`. * Optimizer: Optimize `T = BOOL(X) + TYPE_CHECK(T, true)` to just `BOOL` Resolves php/php-src#18411 --- UPGRADING | 4 ++ Zend/Optimizer/block_pass.c | 61 ++++++++++++++++++++++- ext/opcache/tests/match/005.phpt | 49 ++++++++++++++++++ ext/opcache/tests/opt/block_pass_007.phpt | 49 ++++++++++++++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/match/005.phpt create mode 100644 ext/opcache/tests/opt/block_pass_007.phpt diff --git a/UPGRADING b/UPGRADING index 199162177fe99..7cace1e173cbc 100644 --- a/UPGRADING +++ b/UPGRADING @@ -479,6 +479,10 @@ PHP 8.5 UPGRADE NOTES 14. Performance Improvements ======================================== +- Core: + . Remove OPcodes for identity comparisons against booleans, particularly + for the match(true) pattern. + - ReflectionProperty: . Improved performance of the following methods: getValue(), getRawValue(), isInitialized(), setValue(), setRawValue(). diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 2b6d71c385457..96a0e81f03825 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -470,7 +470,67 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array goto optimize_bool; } break; + case ZEND_IS_IDENTICAL: + if (opline->op1_type == IS_CONST && + opline->op2_type == IS_CONST) { + goto optimize_constant_binary_op; + } + if (opline->op1_type == IS_CONST && + (Z_TYPE(ZEND_OP1_LITERAL(opline)) <= IS_TRUE && Z_TYPE(ZEND_OP1_LITERAL(opline)) >= IS_NULL)) { + /* IS_IDENTICAL(TRUE, T) => TYPE_CHECK(T, TRUE) + * IS_IDENTICAL(FALSE, T) => TYPE_CHECK(T, FALSE) + * IS_IDENTICAL(NULL, T) => TYPE_CHECK(T, NULL) + */ + opline->opcode = ZEND_TYPE_CHECK; + opline->extended_value = (1 << Z_TYPE(ZEND_OP1_LITERAL(opline))); + COPY_NODE(opline->op1, opline->op2); + SET_UNUSED(opline->op2); + ++(*opt_count); + goto optimize_type_check; + } else if (opline->op2_type == IS_CONST && + (Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_TRUE && Z_TYPE(ZEND_OP2_LITERAL(opline)) >= IS_NULL)) { + /* IS_IDENTICAL(T, TRUE) => TYPE_CHECK(T, TRUE) + * IS_IDENTICAL(T, FALSE) => TYPE_CHECK(T, FALSE) + * IS_IDENTICAL(T, NULL) => TYPE_CHECK(T, NULL) + */ + opline->opcode = ZEND_TYPE_CHECK; + opline->extended_value = (1 << Z_TYPE(ZEND_OP2_LITERAL(opline))); + SET_UNUSED(opline->op2); + ++(*opt_count); + goto optimize_type_check; + } + break; + case ZEND_TYPE_CHECK: +optimize_type_check: + if (opline->extended_value == (1 << IS_TRUE) || opline->extended_value == (1 << IS_FALSE)) { + if (opline->op1_type == IS_TMP_VAR && + !zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) { + src = VAR_SOURCE(opline->op1); + + if (src) { + switch (src->opcode) { + case ZEND_BOOL: + case ZEND_BOOL_NOT: + /* T = BOOL(X) + TYPE_CHECK(T, TRUE) -> BOOL(X), NOP + * T = BOOL(X) + TYPE_CHECK(T, FALSE) -> BOOL_NOT(X), NOP + * T = BOOL_NOT(X) + TYPE_CHECK(T, TRUE) -> BOOL_NOT(X), NOP + * T = BOOL_NOT(X) + TYPE_CHECK(T, FALSE) -> BOOL(X), NOP + */ + src->opcode = + ((src->opcode == ZEND_BOOL) == (opline->extended_value == (1 << IS_TRUE))) ? + ZEND_BOOL : ZEND_BOOL_NOT; + COPY_NODE(src->result, opline->result); + SET_VAR_SOURCE(src); + MAKE_NOP(opline); + ++(*opt_count); + break; + } + } + } + } + break; + case ZEND_BOOL: case ZEND_BOOL_NOT: optimize_bool: @@ -803,7 +863,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array case ZEND_SR: case ZEND_IS_SMALLER: case ZEND_IS_SMALLER_OR_EQUAL: - case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_BOOL_XOR: case ZEND_BW_OR: diff --git a/ext/opcache/tests/match/005.phpt b/ext/opcache/tests/match/005.phpt new file mode 100644 index 0000000000000..5726336d53922 --- /dev/null +++ b/ext/opcache/tests/match/005.phpt @@ -0,0 +1,49 @@ +--TEST-- +Match expression true +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 +--EXTENSIONS-- +opcache +--FILE-- + 'en', + !!preg_match('/Bienvenue/', $text), !!preg_match('/Bonjour/', $text) => 'fr', + default => 'other', +}; + +var_dump($result); + +?> +--EXPECTF-- +$_main: + ; (lines=20, args=0, vars=2, tmps=1) + ; (after optimizer) + ; %s +0000 ASSIGN CV0($text) string("Bienvenue chez nous") +0001 T2 = FRAMELESS_ICALL_2(preg_match) string("/Welcome/") CV0($text) +0002 JMPNZ T2 0010 +0003 T2 = FRAMELESS_ICALL_2(preg_match) string("/Hello/") CV0($text) +0004 JMPNZ T2 0010 +0005 T2 = FRAMELESS_ICALL_2(preg_match) string("/Bienvenue/") CV0($text) +0006 JMPNZ T2 0012 +0007 T2 = FRAMELESS_ICALL_2(preg_match) string("/Bonjour/") CV0($text) +0008 JMPNZ T2 0012 +0009 JMP 0014 +0010 T2 = QM_ASSIGN string("en") +0011 JMP 0015 +0012 T2 = QM_ASSIGN string("fr") +0013 JMP 0015 +0014 T2 = QM_ASSIGN string("other") +0015 ASSIGN CV1($result) T2 +0016 INIT_FCALL 1 %d string("var_dump") +0017 SEND_VAR CV1($result) 1 +0018 DO_ICALL +0019 RETURN int(1) +string(2) "fr" diff --git a/ext/opcache/tests/opt/block_pass_007.phpt b/ext/opcache/tests/opt/block_pass_007.phpt new file mode 100644 index 0000000000000..4f3d334406a42 --- /dev/null +++ b/ext/opcache/tests/opt/block_pass_007.phpt @@ -0,0 +1,49 @@ +--TEST-- +Block Pass 007: BOOL + TYPE_CHECK +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=22, args=0, vars=1, tmps=1) + ; (after optimizer) + ; %s +0000 INIT_FCALL 2 %d string("random_int") +0001 SEND_VAL int(1) 1 +0002 SEND_VAL int(2) 2 +0003 V1 = DO_ICALL +0004 ASSIGN CV0($f) V1 +0005 INIT_FCALL 1 %d string("var_dump") +0006 T1 = BOOL_NOT CV0($f) +0007 SEND_VAL T1 1 +0008 DO_ICALL +0009 INIT_FCALL 1 %d string("var_dump") +0010 T1 = BOOL CV0($f) +0011 SEND_VAL T1 1 +0012 DO_ICALL +0013 INIT_FCALL 1 %d string("var_dump") +0014 T1 = BOOL CV0($f) +0015 SEND_VAL T1 1 +0016 DO_ICALL +0017 INIT_FCALL 1 %d string("var_dump") +0018 T1 = BOOL_NOT CV0($f) +0019 SEND_VAL T1 1 +0020 DO_ICALL +0021 RETURN int(1) +bool(false) +bool(true) +bool(true) +bool(false) From 82e09db0e90aa5f0589f2f63033c056471bf777f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 29 Apr 2025 22:48:08 +0200 Subject: [PATCH 436/503] Use reverse-unwinding goto-style error-handling in grapheme_levenshtein (#18451) This reduces repetition and makes it harder to accidentally miss cleaning up something. --- ext/intl/grapheme/grapheme_string.c | 79 ++++++++++++----------------- 1 file changed, 32 insertions(+), 47 deletions(-) diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 08612fd1c37df..bfc352bdca28a 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -980,8 +980,8 @@ PHP_FUNCTION(grapheme_levenshtein) intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); - efree(ustring1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_ustring1; } intl_convert_utf8_to_utf16(&ustring2, &ustring2_len, pstr2, ZSTR_LEN(string2), &ustatus); @@ -990,9 +990,8 @@ PHP_FUNCTION(grapheme_levenshtein) intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); - efree(ustring2); - efree(ustring1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_ustring2; } UBreakIterator *bi1, *bi2; @@ -1002,14 +1001,12 @@ PHP_FUNCTION(grapheme_levenshtein) strlen_2 = grapheme_split_string(ustring2, ustring2_len, NULL, 0); if (strlen_1 == 0) { - efree(ustring1); - efree(ustring2); - RETURN_LONG(strlen_2 * cost_ins); + RETVAL_LONG(strlen_2 * cost_ins); + goto out_ustring2; } if (strlen_2 == 0) { - efree(ustring1); - efree(ustring2); - RETURN_LONG(strlen_1 * cost_del); + RETVAL_LONG(strlen_1 * cost_del); + goto out_ustring2; } unsigned char u_break_iterator_buffer1[U_BRK_SAFECLONE_BUFFERSIZE]; @@ -1018,33 +1015,25 @@ PHP_FUNCTION(grapheme_levenshtein) if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #1 ($string1)", 0); - efree(ustring2); - efree(ustring1); - ubrk_close(bi1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_bi1; } bi2 = grapheme_get_break_iterator(u_break_iterator_buffer2, &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #2 ($string2)", 0); - efree(ustring2); - efree(ustring1); - ubrk_close(bi2); - ubrk_close(bi1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_bi2; } - ubrk_setText(bi1, ustring1, ustring1_len, &ustatus); + ubrk_setText(bi1, ustring1, ustring1_len, &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #1 ($string1)", 0); - efree(ustring2); - efree(ustring1); - ubrk_close(bi2); - ubrk_close(bi1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_bi2; } ubrk_setText(bi2, ustring2, ustring2_len, &ustatus); @@ -1052,23 +1041,16 @@ PHP_FUNCTION(grapheme_levenshtein) intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #2 ($string2)", 0); - efree(ustring2); - efree(ustring1); - ubrk_close(bi2); - ubrk_close(bi1); - RETURN_FALSE; + RETVAL_FALSE; + goto out_bi2; } UCollator *collator = ucol_open("", &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); intl_error_set_custom_msg(NULL, "Error on ucol_open", 0); - efree(ustring2); - efree(ustring1); - ubrk_close(bi2); - ubrk_close(bi1); - ucol_close(collator); - RETURN_FALSE; + RETVAL_FALSE; + goto out_collator; } zend_long *p1, *p2, *tmp; @@ -1118,19 +1100,22 @@ PHP_FUNCTION(grapheme_levenshtein) p2 = tmp; } - ucol_close(collator); - - ubrk_close(bi1); - ubrk_close(bi2); - - efree(ustring1); - efree(ustring2); - retval = p1[strlen_2]; + RETVAL_LONG(retval); - efree(p1); efree(p2); - RETURN_LONG(retval); + efree(p1); + +out_collator: + ucol_close(collator); +out_bi2: + ubrk_close(bi2); +out_bi1: + ubrk_close(bi1); +out_ustring2: + efree(ustring2); +out_ustring1: + efree(ustring1); } /* }}} */ From ad65698a483f9475331c6697f0ab5456d60e293b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 27 Apr 2025 18:25:25 +0100 Subject: [PATCH 437/503] ext/curl: CURLOPT_FOLLOWLOCATION option handling. it had been considered as boolean for years but since 8.13, it can accept values beyond 1L, respectively CURLFOLLOW_OBEYCODE and CURLFOLLOW_FIRSTONLY. close GH-18444 --- NEWS | 4 +++ UPGRADING | 15 ++++++++ ext/curl/curl.stub.php | 18 ++++++++++ ext/curl/curl_arginfo.h | 11 +++++- ext/curl/interface.c | 6 +--- .../curl_setopt_CURLOPT_FOLLOWLOCATION.phpt | 36 +++++++++++++++++++ 6 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt diff --git a/NEWS b/NEWS index 4d8e32cb9d02c..286fb43b22de0 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,10 @@ PHP NEWS . Fixed GH-17956 - development server 404 page does not adapt to mobiles. (pascalchevrel) +- CURL: + . Added CURLFOLLOW_ALL, CURLFOLLOW_OBEYCODE and CURLFOLLOW_FIRSTONLY + values for CURLOPT_FOLLOLOCATION curl_easy_setopt option. (David Carlier) + - COM: . Fixed property access of PHP objects wrapped in variant. (cmb) . Fixed method calls for PHP objects wrapped in variant. (cmb) diff --git a/UPGRADING b/UPGRADING index 7cace1e173cbc..11c63f1f4331d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -159,6 +159,13 @@ PHP 8.5 UPGRADE NOTES CURLOPT_INFILESIZE only accepts a 32-bit signed integer as the file size (2.0 GiB) even on 64-bit systems. CURLOPT_INFILESIZE_LARGE accepts the largest integer value the system can handle. + . Added CURLFOLLOW_OBEYCODE, CURLFOLLOW_FIRSTONLY and CURLFOLLOW_ALL values for + CURLOPT_FOLLOWLOCATION curl_easy_setopt option. + CURLFOLLOW_OBEYCODE to follow more strictly in regard of redirect + if they are allowed. CURLFOLLOW_FIRSTONLY to follow only the + first redirect thus if there any follow up redirect, it won't go + any further. CURLFOLLOW_ALL is equivalent to set CURLOPT_FOLLOWLOCATION + to true. - DOM: . Added Dom\Element::$outerHTML. @@ -361,6 +368,11 @@ PHP 8.5 UPGRADE NOTES 9. Other Changes to Extensions ======================================== +- Curl: + . curl_easy_setopt with CURLOPT_FOLLOWLOCATION option's value no longer + is treated as boolean but integer to handle CURLFOLLOW_OBEYCODE and + CURLFOLLOW_FIRSTONLY. + - Fileinfo: . Upgraded to file 5.46. . The return type of finfo_close() has been changed to true, rather @@ -387,6 +399,9 @@ PHP 8.5 UPGRADE NOTES . CURLINFO_HTTPAUTH_USED. . CURLINFO_PROXYAUTH_USED. . CURLOPT_INFILESIZE_LARGE. + . CURLFOLLOW_ALL. + . CURLFOLLOW_OBEYCODE. + . CURLFOLLOW_FIRSTONLY. - Intl: . DECIMAL_COMPACT_SHORT. diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index 6a73913f8a85e..cbcb52bc7b0a2 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -497,6 +497,24 @@ */ const CURLOPT_DEBUGFUNCTION = UNKNOWN; +#if LIBCURL_VERSION_NUM >= 0x080d00 /* Available since 8.13.0 */ +/** + * @var int + * @cvalue CURLFOLLOW_ALL + */ +const CURLFOLLOW_ALL = UNKNOWN; +/** + * @var int + * @cvalue CURLFOLLOW_OBEYCODE + */ +const CURLFOLLOW_OBEYCODE = UNKNOWN; +/** + * @var int + * @cvalue CURLFOLLOW_FIRSTONLY + */ +const CURLFOLLOW_FIRSTONLY = UNKNOWN; +#endif + /** * @var int * @cvalue CURLINFO_TEXT diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index 53a59fe47be49..8928da3f47453 100644 --- a/ext/curl/curl_arginfo.h +++ b/ext/curl/curl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 77da3a34f08b3e932a0545f72b41bf0353e8b157 */ + * Stub hash: 792cdfa8a8ce190d73dffe679c51a41a2ee46cd7 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) @@ -326,6 +326,15 @@ static void register_curl_symbols(int module_number) REGISTER_LONG_CONSTANT("CURLOPT_WRITEHEADER", CURLOPT_WRITEHEADER, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION, CONST_PERSISTENT); +#if LIBCURL_VERSION_NUM >= 0x080d00 /* Available since 8.13.0 */ + REGISTER_LONG_CONSTANT("CURLFOLLOW_ALL", CURLFOLLOW_ALL, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x080d00 /* Available since 8.13.0 */ + REGISTER_LONG_CONSTANT("CURLFOLLOW_OBEYCODE", CURLFOLLOW_OBEYCODE, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x080d00 /* Available since 8.13.0 */ + REGISTER_LONG_CONSTANT("CURLFOLLOW_FIRSTONLY", CURLFOLLOW_FIRSTONLY, CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("CURLINFO_TEXT", CURLINFO_TEXT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLINFO_HEADER_IN", CURLINFO_HEADER_IN, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLINFO_DATA_IN", CURLINFO_DATA_IN, CONST_PERSISTENT); diff --git a/ext/curl/interface.c b/ext/curl/interface.c index a087da78c37e4..7328401f516fd 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1863,6 +1863,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue #if LIBCURL_VERSION_NUM >= 0x080900 /* Available since 8.9.0 */ case CURLOPT_TCP_KEEPCNT: #endif + case CURLOPT_FOLLOWLOCATION: lval = zval_get_long(zvalue); if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) { @@ -2210,11 +2211,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue /* Do nothing, just backward compatibility */ break; - case CURLOPT_FOLLOWLOCATION: - lval = zend_is_true(zvalue); - error = curl_easy_setopt(ch->cp, option, lval); - break; - case CURLOPT_POSTFIELDS: if (Z_TYPE_P(zvalue) == IS_ARRAY) { if (zend_hash_num_elements(Z_ARRVAL_P(zvalue)) == 0) { diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt new file mode 100644 index 0000000000000..31661e2eaffb9 --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt @@ -0,0 +1,36 @@ +--TEST-- +CURLOPT_FOLLOWLOCATION values +--EXTENSIONS-- +curl +--SKIPIF-- += 8.13.0'); +?> +--FILE-- + +--EXPECTF-- +bool(true) +string(%d) "%s" +bool(true) +string(%d) "%s" +bool(true) +string(%d) "%s" +bool(true) +string(%d) "%s" + From bb431f124c95b9ba003f15df1ad6fbbe768ec7c8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Apr 2025 22:41:32 +0100 Subject: [PATCH 438/503] Fixed GH-18458: `Authorization` set with CURLOPT_USERPWD with NULL value. --- ext/curl/interface.c | 18 +++++++++++++++++- ext/curl/tests/gh18458.phpt | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ext/curl/tests/gh18458.phpt diff --git a/ext/curl/interface.c b/ext/curl/interface.c index fe647dbafd4de..dd4e0db3d77b6 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1900,7 +1900,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_SSLKEYTYPE: case CURLOPT_SSL_CIPHER_LIST: case CURLOPT_USERAGENT: - case CURLOPT_USERPWD: case CURLOPT_COOKIELIST: case CURLOPT_FTP_ALTERNATIVE_TO_USER: case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: @@ -1998,6 +1997,23 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue return ret; } + case CURLOPT_USERPWD: + { + if (Z_ISNULL_P(zvalue)) { + // Authorization header would be implictly set + // with an empty string thus we explictly set the option + // to null to avoid this unwarranted side effect + error = curl_easy_setopt(ch->cp, option, NULL); + } else { + zend_string *tmp_str; + zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); + zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + zend_tmp_string_release(tmp_str); + return ret; + } + break; + } + /* Curl nullable string options */ case CURLOPT_CUSTOMREQUEST: case CURLOPT_FTPPORT: diff --git a/ext/curl/tests/gh18458.phpt b/ext/curl/tests/gh18458.phpt new file mode 100644 index 0000000000000..34be6797e48dd --- /dev/null +++ b/ext/curl/tests/gh18458.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-18458 authorization header is set despite CURLOPT_USERPWD set to null +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(false) From d9d58c9d79a2fce949e4a8bdd5f02e02af017ca8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Apr 2025 22:48:16 +0100 Subject: [PATCH 439/503] Revert "Fixed GH-18458: `Authorization` set with CURLOPT_USERPWD with NULL value." This reverts commit bb431f124c95b9ba003f15df1ad6fbbe768ec7c8. --- ext/curl/interface.c | 18 +----------------- ext/curl/tests/gh18458.phpt | 20 -------------------- 2 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 ext/curl/tests/gh18458.phpt diff --git a/ext/curl/interface.c b/ext/curl/interface.c index dd4e0db3d77b6..fe647dbafd4de 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1900,6 +1900,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_SSLKEYTYPE: case CURLOPT_SSL_CIPHER_LIST: case CURLOPT_USERAGENT: + case CURLOPT_USERPWD: case CURLOPT_COOKIELIST: case CURLOPT_FTP_ALTERNATIVE_TO_USER: case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: @@ -1997,23 +1998,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue return ret; } - case CURLOPT_USERPWD: - { - if (Z_ISNULL_P(zvalue)) { - // Authorization header would be implictly set - // with an empty string thus we explictly set the option - // to null to avoid this unwarranted side effect - error = curl_easy_setopt(ch->cp, option, NULL); - } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - return ret; - } - break; - } - /* Curl nullable string options */ case CURLOPT_CUSTOMREQUEST: case CURLOPT_FTPPORT: diff --git a/ext/curl/tests/gh18458.phpt b/ext/curl/tests/gh18458.phpt deleted file mode 100644 index 34be6797e48dd..0000000000000 --- a/ext/curl/tests/gh18458.phpt +++ /dev/null @@ -1,20 +0,0 @@ ---TEST-- -GH-18458 authorization header is set despite CURLOPT_USERPWD set to null ---EXTENSIONS-- -curl ---SKIPIF-- - ---FILE-- - ---EXPECT-- -bool(false) From c5f3281446b5bf0ad3420db17438f04313d45159 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Wed, 30 Apr 2025 08:05:28 +0900 Subject: [PATCH 440/503] ext/bcmath: Improving `bcpow()` performance (#18099) --- ext/bcmath/bcmath.c | 31 ++++- ext/bcmath/libbcmath/src/bcmath.h | 12 +- ext/bcmath/libbcmath/src/private.h | 3 + ext/bcmath/libbcmath/src/raise.c | 216 ++++++++++++++++++++++++----- ext/bcmath/libbcmath/src/recmul.c | 156 ++++++--------------- 5 files changed, 258 insertions(+), 160 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 1e0e6d14d81eb..2e9cb6c3ad774 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -179,6 +179,26 @@ static zend_result php_str2num(bc_num *num, const zend_string *str) } /* }}} */ +static void bc_pow_err(bc_raise_status status, uint32_t arg_num) +{ + /* If arg_num is 0, it means it is an op */ + switch (status) { + case BC_RAISE_STATUS_DIVIDE_BY_ZERO: + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero"); + break; + case BC_RAISE_STATUS_LEN_IS_OVERFLOW: + case BC_RAISE_STATUS_SCALE_IS_OVERFLOW: + case BC_RAISE_STATUS_FULLLEN_IS_OVERFLOW: + if (arg_num == 0) { + zend_value_error("exponent is too large, the number of digits overflowed"); + } else { + zend_argument_value_error(arg_num, "exponent is too large, the number of digits overflowed"); + } + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } +} + /* {{{ Returns the sum of two arbitrary precision numbers */ PHP_FUNCTION(bcadd) { @@ -615,11 +635,11 @@ PHP_FUNCTION(bcpow) goto cleanup; } - if (!bc_raise(first, exponent, &result, scale)) { - zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero"); + bc_raise_status ret_status = bc_raise(first, exponent, &result, scale); + if (UNEXPECTED(ret_status != BC_RAISE_STATUS_OK)) { + bc_pow_err(ret_status, 2); goto cleanup; } - RETVAL_NEW_STR(bc_num2str_ex(result, scale)); cleanup: { @@ -1144,8 +1164,9 @@ static zend_result bcmath_number_pow_internal( } return FAILURE; } - if (!bc_raise(n1, exponent, ret, *scale)) { - zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero"); + bc_raise_status ret_status = bc_raise(n1, exponent, ret, *scale); + if (UNEXPECTED(ret_status != BC_RAISE_STATUS_OK)) { + bc_pow_err(ret_status, is_op ? 0 : 1); return FAILURE; } bc_rm_trailing_zeros(*ret); diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index 1f05ad51f7f26..fa335ae404808 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -147,8 +147,6 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale); *(result) = mul_ex; \ } while (0) -bc_num bc_square(bc_num n1, size_t scale); - bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, size_t scale); bool bc_modulo(bc_num num1, bc_num num2, bc_num *resul, size_t scale); @@ -159,6 +157,14 @@ bc_num bc_floor_or_ceil(bc_num num, bool is_floor); size_t bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result); +typedef enum { + BC_RAISE_STATUS_OK, + BC_RAISE_STATUS_LEN_IS_OVERFLOW, + BC_RAISE_STATUS_SCALE_IS_OVERFLOW, + BC_RAISE_STATUS_FULLLEN_IS_OVERFLOW, + BC_RAISE_STATUS_DIVIDE_BY_ZERO, +} bc_raise_status; + typedef enum { OK, BASE_HAS_FRACTIONAL, @@ -170,7 +176,7 @@ typedef enum { raise_mod_status bc_raisemod(bc_num base, bc_num exponent, bc_num mod, bc_num *result, size_t scale); -bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale); +bc_raise_status bc_raise(bc_num base, long exponent, bc_num *result, size_t scale); void bc_raise_bc_exponent(bc_num base, bc_num exponent, bc_num *resul, size_t scale); diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 91facfb2f8b40..de9045a16c7e5 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -84,6 +84,9 @@ static const BC_VECTOR BC_POW_10_LUT[9] = { bcmath_compare_result _bc_do_compare (bc_num n1, bc_num n2, size_t scale, bool use_sign); bc_num _bc_do_add (bc_num n1, bc_num n2); bc_num _bc_do_sub (bc_num n1, bc_num n2); +void bc_multiply_vector( + const BC_VECTOR *n1_vector, size_t n1_arr_size, const BC_VECTOR *n2_vector, size_t n2_arr_size, + BC_VECTOR *prod_vector, size_t prod_arr_size); void _bc_rm_leading_zeros (bc_num num); #endif diff --git a/ext/bcmath/libbcmath/src/raise.c b/ext/bcmath/libbcmath/src/raise.c index 1e283864694b6..5df8130c24219 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -30,31 +30,155 @@ *************************************************************************/ #include "bcmath.h" +#include "convert.h" +#include "private.h" #include #include #include -void bc_square_ex(bc_num n1, bc_num *result, size_t scale_min) { - bc_num square_ex = bc_square(n1, scale_min); - bc_free_num(result); - *(result) = square_ex; +static inline size_t bc_multiply_vector_ex( + BC_VECTOR **n1_vector, size_t n1_arr_size, BC_VECTOR *n2_vector, size_t n2_arr_size, BC_VECTOR **result_vector) +{ + size_t result_arr_size = n1_arr_size + n2_arr_size; + bc_multiply_vector(*n1_vector, n1_arr_size, n2_vector, n2_arr_size, *result_vector, result_arr_size); + + /* Eliminate extra zeros because they increase the number of calculations. */ + while ((*result_vector)[result_arr_size - 1] == 0) { + result_arr_size--; + } + + /* Swap n1_vector and result_vector. */ + BC_VECTOR *tmp = *n1_vector; + *n1_vector = *result_vector; + *result_vector = tmp; + + return result_arr_size; +} + +static inline size_t bc_square_vector_ex(BC_VECTOR **base_vector, size_t base_arr_size, BC_VECTOR **result_vector) +{ + return bc_multiply_vector_ex(base_vector, base_arr_size, *base_vector, base_arr_size, result_vector); +} + +/* Use "exponentiation by squaring". This is the fast path when the results are small. */ +static inline bc_num bc_fast_raise( + const char *base_end, long exponent, size_t base_len, size_t power_len, size_t power_scale, size_t power_full_len) +{ + BC_VECTOR base_vector = 0; + + /* Convert to BC_VECTOR[] */ + bc_convert_to_vector(&base_vector, base_end, base_len); + + while ((exponent & 1) == 0) { + base_vector *= base_vector; + exponent >>= 1; + } + + /* copy base to power */ + BC_VECTOR power_vector = base_vector; + exponent >>= 1; + + while (exponent > 0) { + base_vector *= base_vector; + if ((exponent & 1) == 1) { + power_vector *= base_vector; + } + exponent >>= 1; + } + + bc_num power = bc_new_num_nonzeroed(power_len, power_scale); + char *pptr = power->n_value; + char *pend = pptr + power_full_len - 1; + + while (pend >= pptr) { + *pend-- = power_vector % BASE; + power_vector /= BASE; + } + return power; +} + +/* Use "exponentiation by squaring". This is the standard path. */ +static bc_num bc_standard_raise( + const char *base_ptr, const char *base_end, long exponent, size_t base_len, size_t power_scale) +{ + /* Remove the leading zeros as they will be filled in later. */ + while (*base_ptr == 0) { + base_ptr++; + base_len--; + } + + size_t base_arr_size = BC_ARR_SIZE_FROM_LEN(base_len); + /* Since it is guaranteed that base_len * exponent does not overflow, there is no possibility of overflow here. */ + size_t max_power_arr_size = base_arr_size * exponent; + + /* The allocated memory area is reused on a rotational basis, so the same size is required. */ + BC_VECTOR *buf = safe_emalloc(max_power_arr_size, sizeof(BC_VECTOR) * 3, 0); + BC_VECTOR *base_vector = buf; + BC_VECTOR *power_vector = base_vector + max_power_arr_size; + BC_VECTOR *tmp_result_vector = power_vector + max_power_arr_size; + + /* Convert to BC_VECTOR[] */ + bc_convert_to_vector(base_vector, base_end, base_len); + + while ((exponent & 1) == 0) { + base_arr_size = bc_square_vector_ex(&base_vector, base_arr_size, &tmp_result_vector); + exponent >>= 1; + } + + /* copy base to power */ + size_t power_arr_size = base_arr_size; + for (size_t i = 0; i < base_arr_size; i++) { + power_vector[i] = base_vector[i]; + } + exponent >>= 1; + + while (exponent > 0) { + base_arr_size = bc_square_vector_ex(&base_vector, base_arr_size, &tmp_result_vector); + if ((exponent & 1) == 1) { + power_arr_size = bc_multiply_vector_ex(&power_vector, power_arr_size, base_vector, base_arr_size, &tmp_result_vector); + } + exponent >>= 1; + } + + /* Convert to bc_num */ + size_t power_leading_zeros = 0; + size_t power_len; + size_t power_full_len = power_arr_size * BC_VECTOR_SIZE; + if (power_full_len > power_scale) { + power_len = power_full_len - power_scale; + } else { + power_len = 1; + power_leading_zeros = power_scale - power_full_len + 1; + power_full_len = power_scale + 1; + } + bc_num power = bc_new_num_nonzeroed(power_len, power_scale); + + char *pptr = power->n_value; + char *pend = pptr + power_full_len - 1; + + /* Pad with leading zeros if necessary. */ + memset(pptr, 0, power_leading_zeros); + pptr += power_leading_zeros; + + bc_convert_vector_to_char(power_vector, pptr, pend, power_arr_size); + + efree(buf); + + return power; } /* Raise "base" to the "exponent" power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a "exponent" is not an integer, only the integer part is used. */ -bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale) { - bc_num temp, power; +bc_raise_status bc_raise(bc_num base, long exponent, bc_num *result, size_t scale) { size_t rscale; - size_t pwrscale; - size_t calcscale; bool is_neg; /* Special case if exponent is a zero. */ if (exponent == 0) { bc_free_num (result); *result = bc_copy_num(BCG(_one_)); - return true; + return BC_RAISE_STATUS_OK; } /* Other initializations. */ @@ -67,44 +191,66 @@ bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale) { rscale = MIN (base->n_scale * exponent, MAX(scale, base->n_scale)); } - /* Set initial value of temp. */ - power = bc_copy_num(base); - pwrscale = base->n_scale; - while ((exponent & 1) == 0) { - pwrscale = 2 * pwrscale; - bc_square_ex(power, &power, pwrscale); - exponent = exponent >> 1; + if (bc_is_zero(base)) { + /* If the exponent is negative, it divides by 0 */ + return is_neg ? BC_RAISE_STATUS_DIVIDE_BY_ZERO : BC_RAISE_STATUS_OK; } - temp = bc_copy_num(power); - calcscale = pwrscale; - exponent = exponent >> 1; - /* Do the calculation. */ - while (exponent > 0) { - pwrscale = 2 * pwrscale; - bc_square_ex(power, &power, pwrscale); - if ((exponent & 1) == 1) { - calcscale = pwrscale + calcscale; - bc_multiply_ex(temp, power, &temp, calcscale); - } - exponent = exponent >> 1; + /* check overflow */ + if (UNEXPECTED(base->n_len > SIZE_MAX / exponent)) { + return BC_RAISE_STATUS_LEN_IS_OVERFLOW; + } + if (UNEXPECTED(base->n_scale > SIZE_MAX / exponent)) { + return BC_RAISE_STATUS_SCALE_IS_OVERFLOW; + } + + size_t base_len = base->n_len + base->n_scale; + size_t power_len = base->n_len * exponent; + size_t power_scale = base->n_scale * exponent; + + /* check overflow */ + if (UNEXPECTED(power_len > SIZE_MAX - power_scale)) { + return BC_RAISE_STATUS_FULLLEN_IS_OVERFLOW; + } + size_t power_full_len = power_len + power_scale; + + sign power_sign; + if (base->n_sign == MINUS && (exponent & 1) == 1) { + power_sign = MINUS; + } else { + power_sign = PLUS; + } + + const char *base_end = base->n_value + base_len - 1; + + bc_num power; + if (base_len <= BC_VECTOR_SIZE && power_full_len <= BC_VECTOR_SIZE * 2) { + power = bc_fast_raise(base_end, exponent, base_len, power_len, power_scale, power_full_len); + } else { + power = bc_standard_raise(base->n_value, base_end, exponent, base_len, power_scale); + } + + _bc_rm_leading_zeros(power); + if (bc_is_zero(power)) { + power->n_sign = PLUS; + power->n_scale = 0; + } else { + power->n_sign = power_sign; } /* Assign the value. */ if (is_neg) { - if (bc_divide(BCG(_one_), temp, result, rscale) == false) { - bc_free_num (&temp); + if (bc_divide(BCG(_one_), power, result, rscale) == false) { bc_free_num (&power); - return false; + return BC_RAISE_STATUS_DIVIDE_BY_ZERO; } - bc_free_num (&temp); + bc_free_num (&power); } else { bc_free_num (result); - *result = temp; + *result = power; (*result)->n_scale = MIN(scale, (*result)->n_scale); } - bc_free_num (&power); - return true; + return BC_RAISE_STATUS_OK; } /* This is used internally by BCMath */ diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index 26ce1641db410..5e69fd7eb0336 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -72,43 +72,37 @@ static inline void bc_fast_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, } } -/* - * Equivalent of bc_fast_mul for small numbers to perform computations - * without using array. - */ -static inline void bc_fast_square(bc_num n1, size_t n1len, bc_num *prod) +static inline void bc_standard_vector_mul( + const BC_VECTOR *n1_vector, size_t n1_arr_size, const BC_VECTOR *n2_vector, size_t n2_arr_size, + BC_VECTOR *prod_vector, size_t prod_arr_size) { - const char *n1end = n1->n_value + n1len - 1; - - BC_VECTOR n1_vector = bc_partial_convert_to_vector(n1end, n1len); - BC_VECTOR prod_vector = n1_vector * n1_vector; - - size_t prodlen = n1len + n1len; - *prod = bc_new_num_nonzeroed(prodlen, 0); - char *pptr = (*prod)->n_value; - char *pend = pptr + prodlen - 1; + for (size_t i = 0; i < prod_arr_size; i++) { + prod_vector[i] = 0; + } - while (pend >= pptr) { - *pend-- = prod_vector % BASE; - prod_vector /= BASE; + /* Multiplication and addition */ + size_t count = 0; + for (size_t i = 0; i < n1_arr_size; i++) { + /* + * This calculation adds the result multiple times to the array entries. + * When multiplying large numbers of digits, there is a possibility of + * overflow, so digit adjustment is performed beforehand. + */ + if (UNEXPECTED(count >= BC_VECTOR_NO_OVERFLOW_ADD_COUNT)) { + bc_mul_carry_calc(prod_vector, prod_arr_size); + count = 0; + } + count++; + for (size_t j = 0; j < n2_arr_size; j++) { + prod_vector[i + j] += n1_vector[i] * n2_vector[j]; + } } -} -/* Common part of functions bc_standard_mul and bc_standard_square - * that takes a vector and converts it to a bc_num */ -static inline void bc_mul_finish_from_vector(BC_VECTOR *prod_vector, size_t prod_arr_size, size_t prodlen, bc_num *prod) { /* * Move a value exceeding 4/8 digits by carrying to the next digit. * However, the last digit does nothing. */ bc_mul_carry_calc(prod_vector, prod_arr_size); - - /* Convert to bc_num */ - *prod = bc_new_num_nonzeroed(prodlen, 0); - char *pptr = (*prod)->n_value; - char *pend = pptr + prodlen - 1; - - bc_convert_vector_to_char(prod_vector, pptr, pend, prod_arr_size); } /* @@ -121,7 +115,6 @@ static inline void bc_mul_finish_from_vector(BC_VECTOR *prod_vector, size_t prod */ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc_num *prod) { - size_t i; const char *n1end = n1->n_value + n1len - 1; const char *n2end = n2->n_value + n2len - 1; size_t prodlen = n1len + n2len; @@ -147,88 +140,24 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc BC_VECTOR *n2_vector = n1_vector + n1_arr_size; BC_VECTOR *prod_vector = n2_vector + n2_arr_size; - for (i = 0; i < prod_arr_size; i++) { - prod_vector[i] = 0; - } - /* Convert to BC_VECTOR[] */ bc_convert_to_vector(n1_vector, n1end, n1len); bc_convert_to_vector(n2_vector, n2end, n2len); - /* Multiplication and addition */ - size_t count = 0; - for (i = 0; i < n1_arr_size; i++) { - /* - * This calculation adds the result multiple times to the array entries. - * When multiplying large numbers of digits, there is a possibility of - * overflow, so digit adjustment is performed beforehand. - */ - if (UNEXPECTED(count >= BC_VECTOR_NO_OVERFLOW_ADD_COUNT)) { - bc_mul_carry_calc(prod_vector, prod_arr_size); - count = 0; - } - count++; - for (size_t j = 0; j < n2_arr_size; j++) { - prod_vector[i + j] += n1_vector[i] * n2_vector[j]; - } - } + /* Do multiply */ + bc_standard_vector_mul(n1_vector, n1_arr_size, n2_vector, n2_arr_size, prod_vector, prod_arr_size); - bc_mul_finish_from_vector(prod_vector, prod_arr_size, prodlen, prod); + /* Convert to bc_num */ + *prod = bc_new_num_nonzeroed(prodlen, 0); + char *pptr = (*prod)->n_value; + char *pend = pptr + prodlen - 1; + bc_convert_vector_to_char(prod_vector, pptr, pend, prod_arr_size); if (allocation_arr_size > BC_STACK_VECTOR_SIZE) { efree(n1_vector); } } -/** This is bc_standard_mul implementation for square */ -static void bc_standard_square(bc_num n1, size_t n1len, bc_num *prod) -{ - size_t i; - const char *n1end = n1->n_value + n1len - 1; - size_t prodlen = n1len + n1len; - - size_t n1_arr_size = BC_ARR_SIZE_FROM_LEN(n1len); - size_t prod_arr_size = BC_ARR_SIZE_FROM_LEN(prodlen); - - BC_VECTOR *buf = safe_emalloc(n1_arr_size + n1_arr_size + prod_arr_size, sizeof(BC_VECTOR), 0); - - BC_VECTOR *n1_vector = buf; - BC_VECTOR *prod_vector = n1_vector + n1_arr_size + n1_arr_size; - - for (i = 0; i < prod_arr_size; i++) { - prod_vector[i] = 0; - } - - /* Convert to BC_VECTOR[] */ - bc_convert_to_vector(n1_vector, n1end, n1len); - - /* Multiplication and addition */ - size_t count = 0; - for (i = 0; i < n1_arr_size; i++) { - /* - * This calculation adds the result multiple times to the array entries. - * When multiplying large numbers of digits, there is a possibility of - * overflow, so digit adjustment is performed beforehand. - */ - if (UNEXPECTED(count >= BC_VECTOR_NO_OVERFLOW_ADD_COUNT)) { - bc_mul_carry_calc(prod_vector, prod_arr_size); - count = 0; - } - count++; - for (size_t j = 0; j < n1_arr_size; j++) { - prod_vector[i + j] += n1_vector[i] * n1_vector[j]; - } - } - - bc_mul_finish_from_vector(prod_vector, prod_arr_size, prodlen, prod); - - efree(buf); -} - -/* The multiply routine. N2 times N1 is put int PROD with the scale of - the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)). - */ - bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale) { bc_num prod; @@ -258,24 +187,17 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale) return prod; } -bc_num bc_square(bc_num n1, size_t scale) +void bc_multiply_vector( + const BC_VECTOR *n1_vector, size_t n1_arr_size, const BC_VECTOR *n2_vector, size_t n2_arr_size, + BC_VECTOR *prod_vector, size_t prod_arr_size) { - bc_num prod; - - size_t len1 = n1->n_len + n1->n_scale; - size_t full_scale = n1->n_scale + n1->n_scale; - size_t prod_scale = MIN(full_scale, MAX(scale, n1->n_scale)); - - if (len1 <= BC_VECTOR_SIZE) { - bc_fast_square(n1, len1, &prod); + if (n1_arr_size == 1 && n2_arr_size == 1) { + prod_vector[0] = *n1_vector * *n2_vector; + if (prod_arr_size == 2) { + prod_vector[1] = prod_vector[0] / BC_VECTOR_BOUNDARY_NUM; + prod_vector[0] %= BC_VECTOR_BOUNDARY_NUM; + } } else { - bc_standard_square(n1, len1, &prod); + bc_standard_vector_mul(n1_vector, n1_arr_size, n2_vector, n2_arr_size, prod_vector, prod_arr_size); } - - prod->n_sign = PLUS; - prod->n_len -= full_scale; - prod->n_scale = prod_scale; - _bc_rm_leading_zeros(prod); - - return prod; } From 39a56a16876a1a70fb4805ed903f3eaac76b6dae Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 30 Apr 2025 08:17:56 +0200 Subject: [PATCH 441/503] Fix opcode length of ZEND_DECLARE_ATTRIBUTED_CONST in JIT-IR component (#18457) Introduced in 3f03f7ed. --- ext/opcache/jit/zend_jit_ir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 5e48903c57c0c..a6140bc8706fa 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -4174,6 +4174,7 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th case ZEND_ASSIGN_STATIC_PROP_REF: case ZEND_ASSIGN_OBJ_REF: case ZEND_FRAMELESS_ICALL_3: + case ZEND_DECLARE_ATTRIBUTED_CONST: zend_jit_set_last_valid_opline(jit, opline + 2); break; default: From 6406d5f7926bc50dd5e55e975cb53d685b915ced Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Wed, 30 Apr 2025 08:18:04 -0600 Subject: [PATCH 442/503] zlib: use zend_string_{extend,truncate} over *_realloc (#18462) These cases seemed obvious enough to me to confidently change as an outsider to zlib. --- ext/zlib/zlib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index f47d879295ced..e73e168708ad7 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -991,7 +991,7 @@ PHP_FUNCTION(inflate_add) case Z_OK: if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ - out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); + out = zend_string_extend(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); ctx->Z.avail_out = CHUNK_SIZE; ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; @@ -1003,7 +1003,7 @@ PHP_FUNCTION(inflate_add) case Z_BUF_ERROR: if (flush_type == Z_FINISH && ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ - out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); + out = zend_string_extend(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); ctx->Z.avail_out = CHUNK_SIZE; ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; @@ -1039,7 +1039,7 @@ PHP_FUNCTION(inflate_add) } while (1); complete: - out = zend_string_realloc(out, buffer_used, 0); + out = zend_string_truncate(out, buffer_used, 0); ZSTR_VAL(out)[buffer_used] = 0; RETURN_STR(out); } @@ -1228,7 +1228,7 @@ PHP_FUNCTION(deflate_add) if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ /* adding 64 more bytes solved every issue I have seen */ - out = zend_string_realloc(out, ZSTR_LEN(out) + 64, 0); + out = zend_string_extend(out, ZSTR_LEN(out) + 64, 0); ctx->Z.avail_out = 64; ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; } From 386ab1dad24566cf46f8d2e6760d00691ef57e50 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 30 Apr 2025 20:52:56 +0200 Subject: [PATCH 443/503] Revert "Fix infinite recursion on deprecated attribute evaluation" This reverts commit 272f7f75e2d4ff25d4dc00b0102c39fdb4f9c573. Reverts GH-17712 for the PHP-8.4 branch. This will be reapplied later with a fix for GH-18463 (GH-18464). --- .../deprecated/class_constants/gh17711.phpt | 28 ------------------- Zend/zend_API.c | 2 +- Zend/zend_compile.c | 4 --- Zend/zend_constants.c | 4 +-- Zend/zend_constants.h | 11 -------- Zend/zend_vm_def.h | 4 +-- Zend/zend_vm_execute.h | 24 ++++------------ ext/opcache/ZendAccelerator.c | 5 ---- 8 files changed, 9 insertions(+), 73 deletions(-) delete mode 100644 Zend/tests/attributes/deprecated/class_constants/gh17711.phpt diff --git a/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt b/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt deleted file mode 100644 index abec209343ab3..0000000000000 --- a/Zend/tests/attributes/deprecated/class_constants/gh17711.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -GH-17711: Infinite recursion through deprecated class constants self-referencing through deprecation message ---FILE-- - ---EXPECTF-- -Deprecated: Constant C::C is deprecated, Message in %s on line %d -string(7) "Message" - -Deprecated: Constant D::C is deprecated, test in %s on line %d -string(4) "test" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 6e254561d3745..5aac3c1f7d77c 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1439,7 +1439,7 @@ ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_ ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) { if (c->ce == class_type) { - if (Z_TYPE(c->value) == IS_CONSTANT_AST || (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) { + if (Z_TYPE(c->value) == IS_CONSTANT_AST) { new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); memcpy(new_c, c, sizeof(zend_class_constant)); c = new_c; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 195c65d504374..832dedc421042 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8822,10 +8822,6 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as if (deprecated) { ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED; - /* For deprecated constants, we need to flag the zval for recursion - * detection. Make sure the zval is separated out of shm. */ - ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS; - ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } } diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 2145cb1915354..d453b8bb73717 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -353,10 +353,8 @@ ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string * } if (UNEXPECTED(ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) { - if ((flags & ZEND_FETCH_CLASS_SILENT) == 0 && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { goto failure; } diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index bd759c2891500..6f0710c0ce63e 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -27,17 +27,6 @@ #define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */ #define CONST_DEPRECATED (1<<2) /* Deprecated */ #define CONST_OWNED (1<<3) /* constant should be destroyed together with class */ -#define CONST_RECURSIVE (1<<4) /* Recursion protection for constant evaluation */ - -#define CONST_IS_RECURSIVE(c) (Z_CONSTANT_FLAGS((c)->value) & CONST_RECURSIVE) -#define CONST_PROTECT_RECURSION(c) \ - do { \ - Z_CONSTANT_FLAGS((c)->value) |= CONST_RECURSIVE; \ - } while (0) -#define CONST_UNPROTECT_RECURSION(c) \ - do { \ - Z_CONSTANT_FLAGS((c)->value) &= ~CONST_RECURSIVE; \ - } while (0) #define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 37e0e0fb43d95..a4fa8063a5bd4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6094,10 +6094,8 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index dadc57d13f278..a8bf9da828593 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7615,10 +7615,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -8777,10 +8775,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -25878,10 +25874,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -26449,10 +26443,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -35290,10 +35282,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -35651,10 +35641,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { - CONST_PROTECT_RECURSION(c); + if (UNEXPECTED(is_constant_deprecated)) { zend_deprecated_class_constant(c, constant_name); - CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index f71f43b330ffa..459449d85f23c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3800,11 +3800,6 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) { val = &c->value; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - /* For deprecated constants, we need to flag the zval for recursion - * detection. Make sure the zval is separated out of shm. */ - if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) { - ok = false; - } if (EXPECTED(zend_update_class_constant(c, key, c->ce) == SUCCESS)) { was_changed = changed = true; } else { From d991215a8ebb464fc1f220fd53513186874b2f51 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 30 Apr 2025 22:38:12 +0200 Subject: [PATCH 444/503] [skip ci] Remove NEWS entry for reverted fix --- NEWS | 2 -- 1 file changed, 2 deletions(-) diff --git a/NEWS b/NEWS index 2331df67b60ec..a261e88435601 100644 --- a/NEWS +++ b/NEWS @@ -35,8 +35,6 @@ PHP NEWS 24 Apr 2025, PHP 8.4.7 - Core: - . Fixed bug GH-17711 and GH-18022 (Infinite recursion on deprecated attribute - evaluation). (ilutov) . Fixed bug GH-18038 (Lazy proxy calls magic methods twice). (Arnaud) . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov) . Fixed bug GH-18268 (Segfault in array_walk() on object with added property From b2876117f01a28f7bfc53ed1c5d31cc7d53a4e00 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 1 May 2025 10:35:43 +0200 Subject: [PATCH 445/503] Update return types of transliterator_get_error_code(), transliterator_get_error_message(), TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage() (#18470) Returning false is impossible. --- UPGRADING | 5 ++++- ext/intl/php_intl.stub.php | 4 ++-- ext/intl/php_intl_arginfo.h | 6 +++--- ext/intl/transliterator/transliterator.stub.php | 4 ++-- ext/intl/transliterator/transliterator_arginfo.h | 6 +++--- ext/intl/transliterator/transliterator_methods.c | 4 ---- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/UPGRADING b/UPGRADING index 11c63f1f4331d..9eb9694233fce 100644 --- a/UPGRADING +++ b/UPGRADING @@ -221,12 +221,15 @@ PHP 8.5 UPGRADE NOTES - Intl: . IntlDateFormatter::setTimeZone()/datefmt_set_timezone() throws an IntlException on uninitialised classes/clone failures. - . grapheme_extract() properly assigns $next value when skipping over invalid starting bytes. Previously there were cases where it would point to the start of the grapheme boundary instead of the end. . Locale:: methods throw a ValueError when locale inputs contain null bytes. + . transliterator_get_error_code(), transliterator_get_error_message() + TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage() + have dropped the false from the return type union. Returning false + was actually never possible. - libxml: . libxml_set_external_entity_loader() now has a formal return type of true. diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index 7d45dcb3601f3..a6a56a88dda2e 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -637,6 +637,6 @@ function transliterator_create_inverse(Transliterator $transliterator): ?Transli function transliterator_transliterate(Transliterator|string $transliterator, string $string, int $start = 0, int $end = -1): string|false {} -function transliterator_get_error_code(Transliterator $transliterator): int|false {} +function transliterator_get_error_code(Transliterator $transliterator): int {} -function transliterator_get_error_message(Transliterator $transliterator): string|false {} +function transliterator_get_error_message(Transliterator $transliterator): string {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index ed4bdcded94be..d5a7f30506710 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: adcf3b6ef720a518087efedbe2b62b10ad4b2624 */ + * Stub hash: 70b621ef9169fd3b913347adc0baf3626584a2c3 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") @@ -792,11 +792,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_transliterator_transliterate, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, end, IS_LONG, 0, "-1") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_transliterator_get_error_code, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_transliterator_get_error_code, 0, 1, IS_LONG, 0) ZEND_ARG_OBJ_INFO(0, transliterator, Transliterator, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_transliterator_get_error_message, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_transliterator_get_error_message, 0, 1, IS_STRING, 0) ZEND_ARG_OBJ_INFO(0, transliterator, Transliterator, 0) ZEND_END_ARG_INFO() diff --git a/ext/intl/transliterator/transliterator.stub.php b/ext/intl/transliterator/transliterator.stub.php index 442a7d5a6a92f..df65b8c7f0d4d 100644 --- a/ext/intl/transliterator/transliterator.stub.php +++ b/ext/intl/transliterator/transliterator.stub.php @@ -49,11 +49,11 @@ public function transliterate(string $string, int $start = 0, int $end = -1): st * @tentative-return-type * @alias transliterator_get_error_code */ - public function getErrorCode(): int|false {} + public function getErrorCode(): int {} /** * @tentative-return-type * @alias transliterator_get_error_message */ - public function getErrorMessage(): string|false {} + public function getErrorMessage(): string {} } diff --git a/ext/intl/transliterator/transliterator_arginfo.h b/ext/intl/transliterator/transliterator_arginfo.h index 0a53fe9a6b9c4..6f74b55521df3 100644 --- a/ext/intl/transliterator/transliterator_arginfo.h +++ b/ext/intl/transliterator/transliterator_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 82af60e0faf01941fbf580da8957a867eda46384 */ + * Stub hash: 300bcc64e5ddaf469bfe4a12e65a6677bf2aea88 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Transliterator___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -26,10 +26,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Transliterator_t ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, end, IS_LONG, 0, "-1") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Transliterator_getErrorCode, 0, 0, MAY_BE_LONG|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Transliterator_getErrorCode, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Transliterator_getErrorMessage, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Transliterator_getErrorMessage, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_METHOD(Transliterator, __construct); diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c index 81e83414a4f5e..ff3ddf5161377 100644 --- a/ext/intl/transliterator/transliterator_methods.c +++ b/ext/intl/transliterator/transliterator_methods.c @@ -437,8 +437,6 @@ PHP_FUNCTION( transliterator_get_error_code ) /* Fetch the object (without resetting its last error code ). */ to = Z_INTL_TRANSLITERATOR_P( object ); - if (to == NULL ) - RETURN_FALSE; RETURN_LONG( (zend_long) TRANSLITERATOR_ERROR_CODE( to ) ); } @@ -460,8 +458,6 @@ PHP_FUNCTION( transliterator_get_error_message ) /* Fetch the object (without resetting its last error code ). */ to = Z_INTL_TRANSLITERATOR_P( object ); - if (to == NULL ) - RETURN_FALSE; /* Return last error message. */ message = intl_error_get_message( TRANSLITERATOR_ERROR_P( to ) ); From e3cac07a9b60fdfa2420db9447ee58634feaab88 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 1 May 2025 00:28:22 +0200 Subject: [PATCH 446/503] Fix numfmt_parse_currency() reference handling Closes GH-18472. --- ext/intl/formatter/formatter_parse.c | 5 ++--- .../numfmt_parse_currency_references.phpt | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 ext/intl/tests/numfmt_parse_currency_references.phpt diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c index 8ea066c586c1f..c31ece7dd9870 100644 --- a/ext/intl/formatter/formatter_parse.c +++ b/ext/intl/formatter/formatter_parse.c @@ -135,7 +135,7 @@ PHP_FUNCTION( numfmt_parse_currency ) FORMATTER_METHOD_INIT_VARS; /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz/|z!", + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz|z!", &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE ) { RETURN_THROWS(); @@ -165,8 +165,7 @@ PHP_FUNCTION( numfmt_parse_currency ) /* Convert parsed currency to UTF-8 and pass it back to caller. */ u8str = intl_convert_utf16_to_utf8(currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo)); INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" ); - zval_ptr_dtor( zcurrency ); - ZVAL_NEW_STR(zcurrency, u8str); + ZEND_TRY_ASSIGN_REF_NEW_STR(zcurrency, u8str); RETVAL_DOUBLE( number ); } diff --git a/ext/intl/tests/numfmt_parse_currency_references.phpt b/ext/intl/tests/numfmt_parse_currency_references.phpt new file mode 100644 index 0000000000000..06427a736930b --- /dev/null +++ b/ext/intl/tests/numfmt_parse_currency_references.phpt @@ -0,0 +1,20 @@ +--TEST-- +numfmt_parse_currency() reference handling +--EXTENSIONS-- +intl +--FILE-- +prop); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Cannot assign string to reference held by property Test::$prop of type int From e3105f5f1e417bd63b4fb06516ee0b40cd33aa81 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 1 May 2025 00:19:51 +0200 Subject: [PATCH 447/503] Fix reference handling of grapheme_extract() Closes GH-18471. --- ext/intl/grapheme/grapheme_string.c | 17 ++++++----------- .../tests/grapheme_extract_references.phpt | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 ext/intl/tests/grapheme_extract_references.phpt diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index a9cfd3d2ea6e5..698b75ce30b46 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -711,15 +711,10 @@ PHP_FUNCTION(grapheme_extract) } if ( NULL != next ) { - if ( !Z_ISREF_P(next) ) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "grapheme_extract: 'next' was not passed by reference", 0 ); - RETURN_FALSE; - } else { - ZVAL_DEREF(next); - /* initialize next */ - zval_ptr_dtor(next); - ZVAL_LONG(next, lstart); + ZEND_ASSERT(Z_ISREF_P(next)); + ZEND_TRY_ASSIGN_REF_LONG(next, lstart); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); } } @@ -776,7 +771,7 @@ PHP_FUNCTION(grapheme_extract) if ( -1 != grapheme_ascii_check((unsigned char *)pstr, MIN(size + 1, str_len)) ) { size_t nsize = MIN(size, str_len); if ( NULL != next ) { - ZVAL_LONG(next, start+nsize); + ZEND_TRY_ASSIGN_REF_LONG(next, start + nsize); } RETURN_STRINGL(pstr, nsize); } @@ -810,7 +805,7 @@ PHP_FUNCTION(grapheme_extract) ubrk_close(bi); if ( NULL != next ) { - ZVAL_LONG(next, start+ret_pos); + ZEND_TRY_ASSIGN_REF_LONG(next, start + ret_pos); } RETURN_STRINGL(((char *)pstr), ret_pos); diff --git a/ext/intl/tests/grapheme_extract_references.phpt b/ext/intl/tests/grapheme_extract_references.phpt new file mode 100644 index 0000000000000..33368279a1a6d --- /dev/null +++ b/ext/intl/tests/grapheme_extract_references.phpt @@ -0,0 +1,19 @@ +--TEST-- +grapheme_extract() references handling +--EXTENSIONS-- +intl +--FILE-- +prop; +grapheme_extract("test", 4, next: $next); +var_dump($test); +?> +--EXPECT-- +object(Test)#1 (1) { + ["prop"]=> + &string(1) "4" +} From a090e59b37d70bca5c114e13db462c44bfbb4140 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:42:53 +0200 Subject: [PATCH 448/503] Fix reference handling of IntlTimeZone::getCanonicalID/intltz_get_canonical_id Closes GH-18469. --- .../tests/intltz_get_canonical_id_refs.phpt | 19 +++++++++++++++++++ ext/intl/timezone/timezone_methods.cpp | 4 +--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 ext/intl/tests/intltz_get_canonical_id_refs.phpt diff --git a/ext/intl/tests/intltz_get_canonical_id_refs.phpt b/ext/intl/tests/intltz_get_canonical_id_refs.phpt new file mode 100644 index 0000000000000..973b7006c7d1a --- /dev/null +++ b/ext/intl/tests/intltz_get_canonical_id_refs.phpt @@ -0,0 +1,19 @@ +--TEST-- +IntlTimeZone::getCanonicalID: refs test +--EXTENSIONS-- +intl +--FILE-- +prop; +print_R(intltz_get_canonical_id('Portugal', $ref)); +var_dump($test); +?> +--EXPECT-- +Europe/Lisbonobject(Test)#1 (1) { + ["prop"]=> + &string(1) "1" +} diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index 580a721e79ec1..d360ab3a688ff 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -291,9 +291,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_canonical_id) RETVAL_NEW_STR(u8str); if (is_systemid) { /* by-ref argument passed */ - ZVAL_DEREF(is_systemid); - zval_ptr_dtor(is_systemid); - ZVAL_BOOL(is_systemid, isSystemID); + ZEND_TRY_ASSIGN_REF_BOOL(is_systemid, isSystemID); } } From 9c555f5a848810074b7d7266eef430c1b55a5589 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 1 May 2025 10:41:57 +0200 Subject: [PATCH 449/503] Update NEWS for the intl reference fixes --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a2c4da767ec6b..37f2f7f081907 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ PHP NEWS correct) (JiriJozif). - Intl: - . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) + . Fix various reference issues. (nielsdos) - Opcache: . Fixed bug GH-18417 (Windows SHM reattachment fails when increasing From 178fc2db82de5e1f6950c061d68770938c0d4a0f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 1 May 2025 12:00:26 +0200 Subject: [PATCH 450/503] [skip ci] Fix var count in opcache test for i386 --- ext/opcache/tests/opt/block_pass_007.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/tests/opt/block_pass_007.phpt b/ext/opcache/tests/opt/block_pass_007.phpt index 4f3d334406a42..b2dca320d9b76 100644 --- a/ext/opcache/tests/opt/block_pass_007.phpt +++ b/ext/opcache/tests/opt/block_pass_007.phpt @@ -18,7 +18,7 @@ var_dump(!!$f === false); ?> --EXPECTF-- $_main: - ; (lines=22, args=0, vars=1, tmps=1) + ; (lines=22, args=0, vars=1, tmps=%d) ; (after optimizer) ; %s 0000 INIT_FCALL 2 %d string("random_int") From dd5733202db669818fc56e80784f38943e6f5df0 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 1 May 2025 16:30:48 +0100 Subject: [PATCH 451/503] Document contributor certification in CONTRIBUTING.md [skip ci] (#18356) --- CONTRIBUTING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5b2e91d63d1b..a91545fa9bd79 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,6 +32,12 @@ had several contributions accepted, commit privileges are often quickly granted. PHP welcomes pull requests to [add tests](#writing-tests), fix bugs and to implement RFCs. Please be sure to include tests as appropriate! +By submitting a pull request, you certify that you have the necessary rights +to submit the work, that the work does not violate any third-party rights +(including those of your employer, if applicable), and that you license your +contribution under the PHP License or under another license if explicitly +accepted by the PHP project maintainers. + If you are fixing a bug, then please submit your PR against the lowest actively supported branch of PHP that the bug affects (only green branches on [the supported version page](https://www.php.net/supported-versions.php) are From f1d259a07be9b252f35f1a377a0a265747c1b6e0 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Fri, 2 May 2025 15:10:16 +0900 Subject: [PATCH 452/503] ext/intl: Fix for the issue where strlen could potentially become negative (#18477) --- ext/intl/grapheme/grapheme_string.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 9bc7796cc35f6..16549f6ece585 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -994,6 +994,10 @@ PHP_FUNCTION(grapheme_levenshtein) int32_t strlen_1, strlen_2; strlen_1 = grapheme_split_string(ustring1, ustring1_len, NULL, 0); strlen_2 = grapheme_split_string(ustring2, ustring2_len, NULL, 0); + if (UNEXPECTED(strlen_1 < 0 || strlen_2 < 0)) { + RETVAL_FALSE; + goto out_ustring2; + } if (strlen_1 == 0) { RETVAL_LONG(strlen_2 * cost_ins); From 59056937bff9b8e36d460391e770fa1fcfa032dd Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 1 May 2025 16:08:05 +0200 Subject: [PATCH 453/503] Fix use-of-uninitialized-value with exception on deprecated const access Closes GH-18478 --- ext/opcache/jit/zend_jit_vm_helpers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index d39a5c44be8bd..4348fbd53ad48 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -380,6 +380,7 @@ static zend_always_inline zend_constant* _zend_quick_get_constant( zend_deprecated_constant(c, c->name); CONST_UNPROTECT_RECURSION(c); if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); return NULL; } } From 60e9fb5a1b99fb812d256363c07c5f697869c0c7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 2 May 2025 15:50:24 +0200 Subject: [PATCH 454/503] Avoid potential integer overflow (#18485) --- ext/intl/grapheme/grapheme_string.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 16549f6ece585..34dd2ed369cfc 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -1053,8 +1053,8 @@ PHP_FUNCTION(grapheme_levenshtein) } zend_long *p1, *p2, *tmp; - p1 = safe_emalloc(strlen_2 + 1, sizeof(zend_long), 0); - p2 = safe_emalloc(strlen_2 + 1, sizeof(zend_long), 0); + p1 = safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0); + p2 = safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0); for (i2 = 0; i2 <= strlen_2; i2++) { p1[i2] = i2 * cost_ins; From 24ab0f1ea10b6d398359c1bdaf7b22dc79b5faa1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Apr 2025 22:42:43 +0100 Subject: [PATCH 455/503] Fixed GH-18458: `Authorization` set with CURLOPT_USERPWD with NULL value. Close GH-18460 --- NEWS | 5 +++++ ext/curl/interface.c | 9 ++++++--- ext/curl/tests/gh18458.phpt | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 ext/curl/tests/gh18458.phpt diff --git a/NEWS b/NEWS index 37f2f7f081907..a0df1b1b6ce1c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.22 +- Curl: + . Fixed GH-18460 (curl_easy_setopt with CURLOPT_USERPWD/CURLOPT_USERNAME/ + CURLOPT_PASSWORD set the Authorization header when set to NULL). + (David Carlier) + - Date: . Fixed bug GH-18076 (Since PHP 8, the date_sun_info() function returns inaccurate sunrise and sunset times, but other calculated times are diff --git a/ext/curl/interface.c b/ext/curl/interface.c index fe647dbafd4de..1a270a1c32cea 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1900,14 +1900,11 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_SSLKEYTYPE: case CURLOPT_SSL_CIPHER_LIST: case CURLOPT_USERAGENT: - case CURLOPT_USERPWD: case CURLOPT_COOKIELIST: case CURLOPT_FTP_ALTERNATIVE_TO_USER: case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: - case CURLOPT_PASSWORD: case CURLOPT_PROXYPASSWORD: case CURLOPT_PROXYUSERNAME: - case CURLOPT_USERNAME: case CURLOPT_NOPROXY: case CURLOPT_SOCKS5_GSSAPI_SERVICE: case CURLOPT_MAIL_FROM: @@ -2021,6 +2018,12 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_HSTS: #endif case CURLOPT_KRBLEVEL: + // Authorization header would be implictly set + // with an empty string thus we explictly set the option + // to null to avoid this unwarranted side effect + case CURLOPT_USERPWD: + case CURLOPT_USERNAME: + case CURLOPT_PASSWORD: { if (Z_ISNULL_P(zvalue)) { error = curl_easy_setopt(ch->cp, option, NULL); diff --git a/ext/curl/tests/gh18458.phpt b/ext/curl/tests/gh18458.phpt new file mode 100644 index 0000000000000..702737ac369ba --- /dev/null +++ b/ext/curl/tests/gh18458.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-18458 (authorization header is set despite CURLOPT_USERPWD set to null) +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%A +bool(false) +%A +bool(false) From bbac6f5c2013c9f114b655ffbc16723d0b0e257b Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 3 May 2025 16:20:18 +0100 Subject: [PATCH 456/503] GH-18344 add Locale::addLikelySubtags/Locale::minimizeSubtags support. (#18487) from a minimized locale, addLikelySubtags augments it with likely subtags so no changes is the locale is already maximized e.g. `en_Latn_US`, minimizeSubtags on the other hand does the opposite operation. --- NEWS | 2 ++ UPGRADING | 2 ++ ext/intl/locale/locale.stub.php | 10 +++++++ ext/intl/locale/locale_arginfo.h | 12 +++++++- ext/intl/locale/locale_methods.c | 46 ++++++++++++++++++++++++++++++ ext/intl/php_intl.stub.php | 4 +++ ext/intl/php_intl_arginfo.h | 12 +++++++- ext/intl/tests/locale_subtags.phpt | 35 +++++++++++++++++++++++ 8 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 ext/intl/tests/locale_subtags.phpt diff --git a/NEWS b/NEWS index 286fb43b22de0..98f8efa4fadfd 100644 --- a/NEWS +++ b/NEWS @@ -94,6 +94,8 @@ PHP NEWS (David Carlier) . Added null bytes presence in locale inputs for Locale class. (David Carlier) . Added grapheme_levenshtein() function. (Yuya Hamada) + . Added Locale::addLikelySubtags/Locale::minimizeSubtags to handle + adding/removing likely subtags to a locale. (David Carlier) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 9eb9694233fce..04bc66c4890c4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -178,6 +178,8 @@ PHP 8.5 UPGRADE NOTES NumberFormatter::CURRENCY_PLURAL, NumberFormatter::CASH_CURRENCY, and NumberFormatter::CURRENCY_STANDARD for various currency-related number formats. + . Added Locale::addLikelySubtags and Locale::minimizeSubtags to + handle likely tags on a given locale. - XSL: . The $namespace argument of XSLTProcessor::getParameter(), diff --git a/ext/intl/locale/locale.stub.php b/ext/intl/locale/locale.stub.php index fcda8f68409ce..03813ecaf194f 100644 --- a/ext/intl/locale/locale.stub.php +++ b/ext/intl/locale/locale.stub.php @@ -138,4 +138,14 @@ public static function acceptFromHttp(string $header): string|false {} * @alias locale_is_right_to_left */ public static function isRightToLeft(string $locale): bool {} + + /** + * @alias locale_add_likely_subtags + */ + public static function addLikelySubtags(string $locale): string|false {} + + /** + * @alias locale_minimize_subtags + */ + public static function minimizeSubtags(string $locale): string|false {} } diff --git a/ext/intl/locale/locale_arginfo.h b/ext/intl/locale/locale_arginfo.h index 40426a1aa9e78..79a16452e2975 100644 --- a/ext/intl/locale/locale_arginfo.h +++ b/ext/intl/locale/locale_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: f09cfd61f3e20576c7f6d5da17a6d9c009d6ab64 */ + * Stub hash: ff1f75bd34a52f57210734e2f5e29efb87566137 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Locale_getDefault, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -66,6 +66,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Locale_isRightToLeft, 0, 1 ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Locale_addLikelySubtags, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Locale_minimizeSubtags arginfo_class_Locale_addLikelySubtags + ZEND_FUNCTION(locale_get_default); ZEND_FUNCTION(locale_set_default); ZEND_FUNCTION(locale_get_primary_language); @@ -85,6 +91,8 @@ ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_accept_from_http); ZEND_FUNCTION(locale_is_right_to_left); +ZEND_FUNCTION(locale_add_likely_subtags); +ZEND_FUNCTION(locale_minimize_subtags); static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("getDefault", zif_locale_get_default, arginfo_class_Locale_getDefault, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) @@ -106,6 +114,8 @@ static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("canonicalize", zif_locale_canonicalize, arginfo_class_Locale_canonicalize, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("acceptFromHttp", zif_locale_accept_from_http, arginfo_class_Locale_acceptFromHttp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("isRightToLeft", zif_locale_is_right_to_left, arginfo_class_Locale_isRightToLeft, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) + ZEND_RAW_FENTRY("addLikelySubtags", zif_locale_add_likely_subtags, arginfo_class_Locale_addLikelySubtags, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) + ZEND_RAW_FENTRY("minimizeSubtags", zif_locale_minimize_subtags, arginfo_class_Locale_minimizeSubtags, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_FE_END }; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index 684f84c7e323a..6f5158fcb46bb 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1639,3 +1639,49 @@ PHP_FUNCTION(locale_is_right_to_left) RETURN_BOOL(uloc_isRightToLeft(locale)); } + +PHP_FUNCTION(locale_add_likely_subtags) +{ + char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = 0; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t maximized_locale_len = uloc_addLikelySubtags(locale, maximized_locale, sizeof(maximized_locale), &status); + INTL_CHECK_STATUS(status, "locale_add_likely_subtags: invalid locale"); + if (maximized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(maximized_locale, maximized_locale_len); +} + +PHP_FUNCTION(locale_minimize_subtags) +{ + char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = 0; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t minimized_locale_len = uloc_minimizeSubtags(locale, minimized_locale, sizeof(minimized_locale), &status); + INTL_CHECK_STATUS(status, "locale_minimize_subtags: invalid locale"); + if (minimized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(minimized_locale, minimized_locale_len); +} diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index a6a56a88dda2e..dfb05a2b50ac5 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -505,6 +505,10 @@ function locale_accept_from_http(string $header): string|false {} function locale_is_right_to_left(string $locale): bool {} +function locale_add_likely_subtags(string $locale): string|false {} + +function locale_minimize_subtags(string $locale): string|false {} + /* msgformat */ function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index d5a7f30506710..b710084910733 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 70b621ef9169fd3b913347adc0baf3626584a2c3 */ + * Stub hash: 0d5b028a1ab8f35e8ee1b51ce3141b6ef782af28 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") @@ -578,6 +578,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_locale_is_right_to_left, 0, 1, _ ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_locale_add_likely_subtags, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_locale_minimize_subtags arginfo_locale_add_likely_subtags + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_msgfmt_create, 0, 2, MessageFormatter, 1) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) @@ -934,6 +940,8 @@ ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_accept_from_http); ZEND_FUNCTION(locale_is_right_to_left); +ZEND_FUNCTION(locale_add_likely_subtags); +ZEND_FUNCTION(locale_minimize_subtags); ZEND_FUNCTION(msgfmt_create); ZEND_FUNCTION(msgfmt_format); ZEND_FUNCTION(msgfmt_format_message); @@ -1123,6 +1131,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(locale_lookup, arginfo_locale_lookup) ZEND_FE(locale_accept_from_http, arginfo_locale_accept_from_http) ZEND_FE(locale_is_right_to_left, arginfo_locale_is_right_to_left) + ZEND_FE(locale_add_likely_subtags, arginfo_locale_add_likely_subtags) + ZEND_FE(locale_minimize_subtags, arginfo_locale_minimize_subtags) ZEND_FE(msgfmt_create, arginfo_msgfmt_create) ZEND_FE(msgfmt_format, arginfo_msgfmt_format) ZEND_FE(msgfmt_format_message, arginfo_msgfmt_format_message) diff --git a/ext/intl/tests/locale_subtags.phpt b/ext/intl/tests/locale_subtags.phpt new file mode 100644 index 0000000000000..0c454706225b5 --- /dev/null +++ b/ext/intl/tests/locale_subtags.phpt @@ -0,0 +1,35 @@ +--TEST-- +Locale::addLikelySubtags/Locale::minimizeSubtags usage +--EXTENSIONS-- +intl +--FILE-- + strlen($locale)); +var_dump(Locale::addLikelySubtags($max) === $max); +var_dump(Locale::minimizeSubtags($locale) === $locale); +var_dump(Locale::addLikelySubtags("%%%invalid%%%locale%%%")); +var_dump(intl_get_error_message()); +var_dump(Locale::minimizeSubtags("%%%Invalid%%%maximized%%%locale%%%")); +var_dump(intl_get_error_message()); +var_dump(Locale::addLikelySubTags(str_repeat($locale, 1024))); +var_dump(intl_get_error_message()); +var_dump(Locale::minimizeSubTags(str_repeat($max, 1024))); +var_dump(intl_get_error_message()); +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +string(67) "locale_add_likely_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(65) "locale_minimize_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(%d) "locale_add_likely_subtags: invalid locale: %s" +bool(false) +string(%d) "locale_minimize_subtags: invalid locale: %s" From 0227d96f48ffadac0e4eae81eb91bfabf0ba754f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 2 May 2025 07:24:15 +0100 Subject: [PATCH 457/503] Fix GH-18481: date_sunrise check sun rise with offset if is finite/is nan close GH-18484 --- NEWS | 2 ++ ext/date/php_date.c | 2 +- ext/date/tests/gh18481.phpt | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ext/date/tests/gh18481.phpt diff --git a/NEWS b/NEWS index a0df1b1b6ce1c..c2e0418487bfd 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS . Fixed bug GH-18076 (Since PHP 8, the date_sun_info() function returns inaccurate sunrise and sunset times, but other calculated times are correct) (JiriJozif). + . Fixed bug GH-18481 (date_sunrise with unexpected nan value for the offset). + (nielsdos/David Carlier) - Intl: . Fix various reference issues. (nielsdos) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index d8a0704ca250a..2347fd55706fa 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5346,7 +5346,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, bool calc_s if (N > 24 || N < 0) { N -= floor(N / 24) * 24; } - if (N > 24 || N < 0) { + if (!(N <= 24 && N >= 0)) { RETURN_FALSE; } diff --git a/ext/date/tests/gh18481.phpt b/ext/date/tests/gh18481.phpt new file mode 100644 index 0000000000000..6617a19474461 --- /dev/null +++ b/ext/date/tests/gh18481.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-18481 (date_sunrise with utcOffset as INF) +--FILE-- + +--EXPECTF-- +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) From a7b78a50916482b2037a36e66e77990332283e81 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 3 May 2025 18:24:44 +0100 Subject: [PATCH 458/503] Fix ext/date: date_sunrise() new tests. close GH-18489 --- ext/date/tests/gh18481.phpt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/date/tests/gh18481.phpt b/ext/date/tests/gh18481.phpt index 6617a19474461..074f244c3a3a3 100644 --- a/ext/date/tests/gh18481.phpt +++ b/ext/date/tests/gh18481.phpt @@ -8,14 +8,22 @@ foreach ([-NAN, NAN, INF, -INF] as $offset) { } ?> --EXPECTF-- -Deprecated: Function date_sunrise() is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d + +Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Function date_sunrise() is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d + +Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Function date_sunrise() is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d + +Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Function date_sunrise() is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d + +Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) From 42ad1c64bf0b0afe57d5a6f8e6d3dcc51e4a142b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 4 May 2025 12:17:56 +0200 Subject: [PATCH 459/503] Backport lexbor/lexbor#274 Co-authored-by: Alex Peattie Closes GH-18490. --- NEWS | 3 +++ ext/dom/lexbor/lexbor/selectors-adapted/selectors.c | 4 ++-- ext/dom/tests/modern/css_selectors/lexbor274.phpt | 13 +++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 ext/dom/tests/modern/css_selectors/lexbor274.phpt diff --git a/NEWS b/NEWS index fe7b2e88a3c58..eb1f4571e86fd 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ PHP NEWS . Fixed bug GH-18481 (date_sunrise with unexpected nan value for the offset). (nielsdos/David Carlier) +- DOM: + . Backport lexbor/lexbor#274. (nielsdos, alexpeattie) + - Intl: . Fix various reference issues. (nielsdos) diff --git a/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c b/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c index 3a40318628f10..765460906e57b 100644 --- a/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c +++ b/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c @@ -3,7 +3,7 @@ * * Author: Alexander Borisov * Adapted for PHP + libxml2 by: Niels Dossche - * Based on Lexbor 2.4.0 (upstream commit e9d35f6384de7bd8c1b79e7111bc3a44f8822967) + * Based on Lexbor (upstream commit b347aa4e4da4e82b1cae18989ceea1aa0278daf1) */ #include @@ -970,7 +970,7 @@ lxb_selectors_state_has_relative(const xmlNode *node, break; } - while (node !=root && node->next == NULL) { + while (node != root && node->next == NULL && node->parent != NULL) { node = node->parent; } diff --git a/ext/dom/tests/modern/css_selectors/lexbor274.phpt b/ext/dom/tests/modern/css_selectors/lexbor274.phpt new file mode 100644 index 0000000000000..836280b166648 --- /dev/null +++ b/ext/dom/tests/modern/css_selectors/lexbor274.phpt @@ -0,0 +1,13 @@ +--TEST-- +Lexbor #274 +--EXTENSIONS-- +dom +--FILE-- +
\n', LIBXML_NOERROR); +var_dump($dom->querySelector('a:has(+ b)')); + +?> +--EXPECT-- +NULL From 4e23d3d49fca2e113a34d14b762399edd220e1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 4 May 2025 13:14:47 +0200 Subject: [PATCH 460/503] [skip ci] Do not interpret PHP version in bug_report.yml as markdown (#18492) --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f0f80bd98e324..53bd4df5a1ca5 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -34,6 +34,7 @@ body: Copyright (c) The PHP Group Zend Engine v4.3.19, Copyright (c) Zend Technologies with Zend OPcache v8.3.19, Copyright (c), by Zend Technologies + render: plain validations: required: true - type: input From 4152ca5c8aad6647724a40efecae57086bd69a14 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 4 May 2025 13:25:42 +0200 Subject: [PATCH 461/503] Fix fuzzer support after CALL VM changes (#18491) --- sapi/fuzzer/fuzzer-execute-common.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sapi/fuzzer/fuzzer-execute-common.h b/sapi/fuzzer/fuzzer-execute-common.h index 3ecd27d3fd991..f5113a5b0e41f 100644 --- a/sapi/fuzzer/fuzzer-execute-common.h +++ b/sapi/fuzzer/fuzzer-execute-common.h @@ -27,12 +27,14 @@ #define FILE_NAME "/tmp/fuzzer.php" #define MAX_STEPS 1000 #define MAX_SIZE (8 * 1024) +#define ZEND_VM_ENTER_BIT 1ULL + static uint32_t steps_left; static bool bailed_out = false; /* Because the fuzzer is always compiled with clang, * we can assume that we don't use global registers / hybrid VM. */ -typedef int (ZEND_FASTCALL *opcode_handler_t)(zend_execute_data *); +typedef zend_op *(ZEND_FASTCALL *opcode_handler_t)(zend_execute_data *, const zend_op *); static zend_always_inline void fuzzer_bailout(void) { bailed_out = true; @@ -51,11 +53,13 @@ static zend_always_inline void fuzzer_step(void) { static void (*orig_execute_ex)(zend_execute_data *execute_data); static void fuzzer_execute_ex(zend_execute_data *execute_data) { + const zend_op *opline = EX(opline); while (1) { - int ret; fuzzer_step(); - if ((ret = ((opcode_handler_t) EX(opline)->handler)(execute_data)) != 0) { - if (ret > 0) { + opline = ((opcode_handler_t) opline->handler)(execute_data, opline); + if ((uintptr_t) opline & ZEND_VM_ENTER_BIT) { + opline = (const zend_op *) ((uintptr_t) opline & ~ZEND_VM_ENTER_BIT); + if (opline) { execute_data = EG(current_execute_data); } else { return; From 8a585856d1a21507c1bee0f4a1fad0e2154c08db Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 2 May 2025 07:11:57 +0100 Subject: [PATCH 462/503] Fix GH-18480: array_splice overflow on array length with offset. close GH-18483 --- NEWS | 4 +++ ext/standard/array.c | 12 ++++---- ext/standard/tests/array/gh18480.phpt | 40 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 ext/standard/tests/array/gh18480.phpt diff --git a/NEWS b/NEWS index c2e0418487bfd..ed6cd4e2e3a57 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.22 +- Core: + . Fixed GH-18480 (array_splice with large values for offset/length arguments). + (nielsdos/David Carlier) + - Curl: . Fixed GH-18460 (curl_easy_setopt with CURLOPT_USERPWD/CURLOPT_USERNAME/ CURLOPT_PASSWORD set the Authorization header when set to NULL). diff --git a/ext/standard/array.c b/ext/standard/array.c index b89deb241f046..4d3c03bce5262 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3252,7 +3252,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H /* If hash for removed entries exists, go until offset+length and copy the entries to it */ if (removed != NULL) { - for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, entry++) { if (Z_TYPE_P(entry) == IS_UNDEF) continue; pos++; Z_TRY_ADDREF_P(entry); @@ -3260,9 +3260,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H zend_hash_packed_del_val(in_hash, entry); } } else { /* otherwise just skip those entries */ - int pos2 = pos; + zend_long pos2 = pos; - for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, entry++) { if (Z_TYPE_P(entry) == IS_UNDEF) continue; pos2++; zend_hash_packed_del_val(in_hash, entry); @@ -3317,7 +3317,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H /* If hash for removed entries exists, go until offset+length and copy the entries to it */ if (removed != NULL) { - for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, p++) { if (Z_TYPE(p->val) == IS_UNDEF) continue; pos++; entry = &p->val; @@ -3330,9 +3330,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H zend_hash_del_bucket(in_hash, p); } } else { /* otherwise just skip those entries */ - int pos2 = pos; + zend_long pos2 = pos; - for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, p++) { if (Z_TYPE(p->val) == IS_UNDEF) continue; pos2++; zend_hash_del_bucket(in_hash, p); diff --git a/ext/standard/tests/array/gh18480.phpt b/ext/standard/tests/array/gh18480.phpt new file mode 100644 index 0000000000000..b9466029d4ee9 --- /dev/null +++ b/ext/standard/tests/array/gh18480.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-18480 (array_splice overflow with large offset / length values) +--FILE-- + PHP_INT_MAX]; + $offset = PHP_INT_MAX; + var_dump(array_splice($a,$offset, $length)); + $a = ["a" => PHP_INT_MAX]; + $offset = PHP_INT_MIN; + var_dump(array_splice($a,$offset, $length)); +} +--EXPECTF-- +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(1) { + [0]=> + int(%d) +} +array(0) { +} +array(1) { + ["a"]=> + int(%d) +} From 1fa076e187f06738a2b267a9a801af6ab27d8677 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 4 May 2025 20:07:06 +0200 Subject: [PATCH 463/503] Cleanup php_posix_passwd_to_array() (#18496) This function can be static, and the error checks are pointless: 1. It's guaranteed that the return value is an array by now, as it is always preceded by array_init(return_value). 2. The null check for pw is pointless as every callee already handles that in a better way. --- ext/posix/posix.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 68d47840c5e20..09a8961196fd9 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -906,12 +906,9 @@ PHP_FUNCTION(posix_getgrgid) } /* }}} */ -int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */ +static void php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */ { - if (NULL == pw) - return 0; - if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY) - return 0; + ZEND_ASSERT(Z_TYPE_P(return_value) == IS_ARRAY); add_assoc_string(return_value, "name", pw->pw_name); add_assoc_string(return_value, "passwd", pw->pw_passwd); @@ -920,7 +917,6 @@ int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */ add_assoc_string(return_value, "gecos", pw->pw_gecos); add_assoc_string(return_value, "dir", pw->pw_dir); add_assoc_string(return_value, "shell", pw->pw_shell); - return 1; } /* }}} */ @@ -973,11 +969,7 @@ PHP_FUNCTION(posix_getpwnam) #endif array_init(return_value); - if (!php_posix_passwd_to_array(pw, return_value)) { - zend_array_destroy(Z_ARR_P(return_value)); - php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array"); - RETVAL_FALSE; - } + php_posix_passwd_to_array(pw, return_value); #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R) efree(buf); #endif @@ -1033,11 +1025,7 @@ PHP_FUNCTION(posix_getpwuid) #endif array_init(return_value); - if (!php_posix_passwd_to_array(pw, return_value)) { - zend_array_destroy(Z_ARR_P(return_value)); - php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array"); - RETVAL_FALSE; - } + php_posix_passwd_to_array(pw, return_value); #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R) efree(pwbuf); #endif From af87ade8b8b27c60aa8f881f5bac4962f4279181 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 4 May 2025 20:07:14 +0200 Subject: [PATCH 464/503] Cleanup php_posix_group_to_array() (#18497) This function can be static, and the error checks are pointless: 1. It's guaranteed that the return value is an array by now, as it is always preceded by array_init(return_value). 2. The null check for g is pointless as every callee already handles that in a better way. --- ext/posix/posix.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 09a8961196fd9..512776d3ced20 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -659,16 +659,12 @@ PHP_FUNCTION(posix_mknod) /* Takes a pointer to posix group and a pointer to an already initialized ZVAL * array container and fills the array with the posix group member data. */ -int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */ +static void php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */ { zval array_members; int count; - if (NULL == g) - return 0; - - if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY) - return 0; + ZEND_ASSERT(Z_TYPE_P(array_group) == IS_ARRAY); array_init(&array_members); zend_hash_real_init_packed(Z_ARRVAL(array_members)); @@ -691,7 +687,6 @@ int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */ } zend_hash_str_update(Z_ARRVAL_P(array_group), "members", sizeof("members")-1, &array_members); add_assoc_long(array_group, "gid", g->gr_gid); - return 1; } /* }}} */ @@ -833,11 +828,7 @@ PHP_FUNCTION(posix_getgrnam) #endif array_init(return_value); - if (!php_posix_group_to_array(g, return_value)) { - zend_array_destroy(Z_ARR_P(return_value)); - php_error_docref(NULL, E_WARNING, "Unable to convert posix group to array"); - RETVAL_FALSE; - } + php_posix_group_to_array(g, return_value); #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) efree(buf); #endif @@ -895,11 +886,7 @@ PHP_FUNCTION(posix_getgrgid) #endif array_init(return_value); - if (!php_posix_group_to_array(g, return_value)) { - zend_array_destroy(Z_ARR_P(return_value)); - php_error_docref(NULL, E_WARNING, "Unable to convert posix group struct to array"); - RETVAL_FALSE; - } + php_posix_group_to_array(g, return_value); #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX) efree(grbuf); #endif From 9ac5b04487164b2921b92110d1b08ffa0a4b5c95 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 4 May 2025 21:44:39 +0100 Subject: [PATCH 465/503] ext/intl: use RETURN_NEW_STR for intl_get*id_windows_id(). (#18501) for non interned return values. --- ext/intl/timezone/timezone_methods.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index f652e9000c40a..6ff0cf5137790 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -646,7 +646,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_windows_id) error = U_ZERO_ERROR; winID = intl_convert_utf16_to_utf8(uWinID.getBuffer(), uWinID.length(), &error); INTL_CHECK_STATUS(error, "could not convert time zone id to UTF-8"); - RETURN_STR(winID); + RETURN_NEW_STR(winID); } /* }}} */ @@ -684,6 +684,6 @@ U_CFUNC PHP_FUNCTION(intltz_get_id_for_windows_id) error = U_ZERO_ERROR; id = intl_convert_utf16_to_utf8(uID.getBuffer(), uID.length(), &error); INTL_CHECK_STATUS(error, "could not convert time zone id to UTF-8"); - RETURN_STR(id); + RETURN_NEW_STR(id); } /* }}} */ From 940ee1a6419b69ef4528d7b478c8d93fa7eb9016 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Sun, 4 May 2025 15:08:37 -0700 Subject: [PATCH 466/503] gen_stub: ZEND_ACC_NODISCARD is for PHP 8.5+ (#18465) --- build/gen_stub.php | 35 +++++++++++++++++++++++++++++------ ext/zend_test/test_arginfo.h | 12 ++++++++++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index d3ffc04c3f890..1919d2e702a27 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1390,7 +1390,13 @@ public function getFunctionEntry(): string { $name = "zim_" . $this->name->getDeclarationClassName() . "_" . $this->name->methodName; if ($isVanillaEntry) { - $functionEntryCode = "\tZEND_ME(" . $this->name->getDeclarationClassName() . ", " . $this->name->methodName . ", $argInfoName, " . implode("|", reset($flagsByPhpVersions)) . ")"; + $template = "\tZEND_ME(" . $this->name->getDeclarationClassName() . ", " . $this->name->methodName . ", $argInfoName, %s)\n"; + $flagsCode = generateVersionDependentFlagCode( + $template, + $flagsByPhpVersions, + $this->minimumPhpVersionIdCompatibility + ); + $functionEntryCode = rtrim(implode("", $flagsCode)); } } } @@ -1406,7 +1412,15 @@ public function getFunctionEntry(): string { $zendName = '"' . $functionName . '"'; $name = "zif_$declarationName"; - if ($isVanillaEntry && reset($flagsByPhpVersions) === ["0"]) { + // Can only use ZEND_FE() if we have no flags for *all* versions + $hasFlags = false; + foreach ($flagsByPhpVersions as $flags) { + if ($flags !== ['0']) { + $hasFlags = true; + break; + } + } + if ($isVanillaEntry && !$hasFlags) { $functionEntryCode = "\tZEND_FE($declarationName, $argInfoName)"; } } @@ -1523,9 +1537,6 @@ private function getArginfoFlagsByPhpVersions(): array case "Deprecated": $flags[] = "ZEND_ACC_DEPRECATED"; break; - case "NoDiscard": - $flags[] = "ZEND_ACC_NODISCARD"; - break; } } @@ -1534,12 +1545,24 @@ private function getArginfoFlagsByPhpVersions(): array $php82AndAboveFlags[] = "ZEND_ACC_COMPILE_TIME_EVAL"; } + $php85AndAboveFlags = $php82AndAboveFlags; + foreach ($this->attributes as $attr) { + switch ($attr->class) { + case "NoDiscard": + $php85AndAboveFlags[] = "ZEND_ACC_NODISCARD"; + break; + } + } + if (empty($flags)) { $flags[] = "0"; } if (empty($php82AndAboveFlags)) { $php82AndAboveFlags[] = "0"; } + if (empty($php85AndAboveFlags)) { + $php85AndAboveFlags[] = "0"; + } return [ PHP_70_VERSION_ID => $flags, @@ -1548,7 +1571,7 @@ private function getArginfoFlagsByPhpVersions(): array PHP_82_VERSION_ID => $php82AndAboveFlags, PHP_83_VERSION_ID => $php82AndAboveFlags, PHP_84_VERSION_ID => $php82AndAboveFlags, - PHP_85_VERSION_ID => $php82AndAboveFlags, + PHP_85_VERSION_ID => $php85AndAboveFlags, ]; } diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 14a634f197d46..cb39e871a4666 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -368,14 +368,22 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("zend_test_deprecated_attr", zif_zend_test_deprecated_attr, arginfo_zend_test_deprecated_attr, ZEND_ACC_DEPRECATED) #endif #if (PHP_VERSION_ID >= 80400) +#if (PHP_VERSION_ID >= 80500) ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, ZEND_ACC_NODISCARD, NULL, NULL) +#elif (PHP_VERSION_ID >= 80400) + ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, 0, NULL, NULL) +#endif #else - ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, ZEND_ACC_NODISCARD) + ZEND_RAW_FENTRY("zend_test_nodiscard", zif_zend_test_nodiscard, arginfo_zend_test_nodiscard, 0) #endif #if (PHP_VERSION_ID >= 80400) +#if (PHP_VERSION_ID >= 80500) ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD, NULL, NULL) +#elif (PHP_VERSION_ID >= 80400) + ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED, NULL, NULL) +#endif #else - ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD) + ZEND_RAW_FENTRY("zend_test_deprecated_nodiscard", zif_zend_test_deprecated_nodiscard, arginfo_zend_test_deprecated_nodiscard, ZEND_ACC_DEPRECATED) #endif #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY("zend_test_aliased", zif_zend_test_void_return, arginfo_zend_test_aliased, 0, NULL, NULL) From c91c6545fefa56abfdef64bf732f41b27e3b9f05 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 5 May 2025 13:36:26 +0200 Subject: [PATCH 467/503] Drop name from mysqli_prop_handler (#18498) It's just not necessary to store this, if we ever need this we can get this from the hash table. --- ext/mysqli/mysqli.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 987183aa9dcb0..d2ea69c6fe98f 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -75,7 +75,6 @@ typedef zend_result (*mysqli_read_t)(mysqli_object *obj, zval *rv, bool quiet); typedef zend_result (*mysqli_write_t)(mysqli_object *obj, zval *newval); typedef struct _mysqli_prop_handler { - zend_string *name; mysqli_read_t read_func; mysqli_write_t write_func; } mysqli_prop_handler; @@ -294,11 +293,11 @@ zval *mysqli_write_property(zend_object *object, zend_string *name, zval *value, void mysqli_add_property(HashTable *h, const char *pname, size_t pname_len, mysqli_read_t r_func, mysqli_write_t w_func) { mysqli_prop_handler p; - p.name = zend_string_init_interned(pname, pname_len, 1); + zend_string *name = zend_string_init_interned(pname, pname_len, 1); p.read_func = (r_func) ? r_func : mysqli_read_na; p.write_func = w_func; - zend_hash_add_mem(h, p.name, &p, sizeof(mysqli_prop_handler)); - zend_string_release_ex(p.name, 1); + zend_hash_add_mem(h, name, &p, sizeof(mysqli_prop_handler)); + zend_string_release_ex(name, 1); } /* }}} */ @@ -344,17 +343,17 @@ HashTable *mysqli_object_get_debug_info(zend_object *object, int *is_temp) { mysqli_object *obj = php_mysqli_fetch_object(object); HashTable *retval, *props = obj->prop_handler; - mysqli_prop_handler *entry; + zend_string *name; retval = zend_new_array(zend_hash_num_elements(props) + 1); - ZEND_HASH_MAP_FOREACH_PTR(props, entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY(props, name) { zval rv; zval *value; - value = mysqli_read_property(object, entry->name, BP_VAR_IS, 0, &rv); + value = mysqli_read_property(object, name, BP_VAR_IS, 0, &rv); if (value != &EG(uninitialized_zval)) { - zend_hash_add(retval, entry->name, value); + zend_hash_add(retval, name, value); } } ZEND_HASH_FOREACH_END(); From 7855c52e8141169fcf7e6b79418f6898608c3eca Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 5 May 2025 13:58:15 +0100 Subject: [PATCH 468/503] ext/standard: gethostbyaddr/gethostbyname using *NEW_STR flavor. (#18502) --- ext/standard/dns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/dns.c b/ext/standard/dns.c index 04477129e3599..bd5720210fdaf 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -163,7 +163,7 @@ PHP_FUNCTION(gethostbyaddr) #endif RETVAL_FALSE; } else { - RETVAL_STR(hostname); + RETVAL_NEW_STR(hostname); } } /* }}} */ @@ -236,7 +236,7 @@ PHP_FUNCTION(gethostbyname) php_error_docref(NULL, E_WARNING, "Host name to ip failed %s", hostname); RETURN_STRINGL(hostname, hostname_len); } else { - RETURN_STR(ipaddr); + RETURN_NEW_STR(ipaddr); } } /* }}} */ From 90da4821a2ad98fd5f4281e62df6a92d5326e2a5 Mon Sep 17 00:00:00 2001 From: Florian Moser Date: Mon, 5 May 2025 15:10:29 +0200 Subject: [PATCH 469/503] ext/gmp: Add GMP ECC test (#18363) Co-authored-by: Gina Peter Banyard --- ext/gmp/tests/gmp_cryptography.phpt | 139 +++++-- ext/gmp/tests/gmp_cryptography_ecc.phpt | 382 ++++++++++++++++++ .../gmp_cryptography_overload_operators.phpt | 112 +++++ 3 files changed, 609 insertions(+), 24 deletions(-) create mode 100644 ext/gmp/tests/gmp_cryptography_ecc.phpt create mode 100644 ext/gmp/tests/gmp_cryptography_overload_operators.phpt diff --git a/ext/gmp/tests/gmp_cryptography.phpt b/ext/gmp/tests/gmp_cryptography.phpt index 771c557e5425a..cb7f17c8ce7da 100644 --- a/ext/gmp/tests/gmp_cryptography.phpt +++ b/ext/gmp/tests/gmp_cryptography.phpt @@ -1,36 +1,127 @@ --TEST-- -test some of the simple operations done in ECC cryptography (GH-16870) +test operations done in finite field and elliptic curve cryptography. (GH-16870) +--DESCRIPTION-- +Test operations using gmp with number sizes useful in cryptography. +To gather the to-be-executed operations, the gmp_cryptography_ecc.phpt and gmp_cryptography_ffc.phpt files have been analysed. + +For finite field crypto (FFC), the operations are executed in a 8192bit prime group, with a 512bit factor. +This is the biggest prime that was standarized in https://datatracker.ietf.org/doc/html/rfc3526. +Note that this is insufficient according to the NIST guidelines for the security strength 256bit. +However, it is doubtful that such big groups (or even bigger ones) are used, as then elliptic curves are much more efficient. + +For elliptic curve crypto (EEC), the operations are executed in a 512bit prime group. +This corresponds to the biggest curve standardized in https://www.secg.org/sec2-v2.pdf. +Operations already executed as part of FCC are ommitted: As FFC operates on larger numbers, ECC operations are implicitly covered. + +Further context: +- See https://www.keylength.com/en/4/ for an overview of the recommended key lengths by NIST. +- See https://doi.org/10.6028/NIST.IR.8547.ipd for a public draft of NIST which proposes to fade-out FFC/ECC crypto by 2035. + +Factors were produced using +$random = gmp_random_bits(512); +$randomHex = strtoupper(gmp_strval($random, 16)); +echo chunk_split(chunk_split($randomHex, 8, " "), 54); --EXTENSIONS-- gmp --FILE-- 0); + + +// prime and b of secp521r1 from https://www.secg.org/sec2-v2.pdf +$p = gmp_init('01FF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF +FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF +FFFFFFFF FFFFFFFF FFFFFFFF', 16); +$b = gmp_init('0051 953EB961 8E1C9A1F 929A21A0 B68540EE A2DA725B 99B315F3 +B8B48991 8EF109E1 56193951 EC7E937B 1652C0BD 3BB1BF07 3573DF88 +3D2C34F1 EF451FD4 6B503F00', 16); -// in ecc crypto key lengths of 256, 384 and 521 (yes, 521, not 512) are typical, -// and the calculations seem to include squaring and cubing the key, -// so test those operations -var_dump((string) gmp_pow($big_128, 2)); -var_dump((string) gmp_pow($big_128, 3)); +$jacobi = gmp_jacobi($b, $p); +var_dump($jacobi === 1); -var_dump((string) gmp_pow($big_256, 2)); -var_dump((string) gmp_pow($big_256, 3)); +$result = gmp_and($p, $b); +var_dump(gmp_cmp($result, $b) === 0); -var_dump((string) gmp_pow($big_384, 2)); -var_dump((string) gmp_pow($big_384, 3)); +$result = gmp_xor($p, $p); +var_dump(gmp_cmp($result, 0) === 0); -var_dump((string) gmp_pow($big_521, 2)); -var_dump((string) gmp_pow($big_521, 3)); +$result = gmp_pow($b, 3); +var_dump(gmp_strval($result, 16)); ?> --EXPECT-- -string(77) "75877646180287003845291692588996321992008024509271171205840397374930023621264" -string(116) "20901178542000013443295783507452967008255111311111391381095411786512605029527130998551663048238767676593252458334912" -string(155) "11214254709783046066761897074581165564696209875788503860615296581570239055173596662994580613114615553617959320367624022951770022252133452732995602203876100" -string(232) "1187560172240926986956555551805946700914014146395850601682624192167183140821546786142042010581624015945796617035803644080855311724420346850512769661608026325318823192181186500090109111010574371273491473985103578154963883352347509000" -string(230) "41175244239511227932271803271789465275501438128816738161335879819867157609061333189838579416997011220296835767015204168726569753974321567200401024149587401209307771709029048946370759582286096704404540466667318675170269947865547236" -string(345) "264213056979683026715444213001489498112251992104549535125497320782388835160296854596249682279610208850530256165562505337646325742090947380083481042994421218556776724906795900034870043631716997303728488772811762108912277655229349137086580494553471889656657230883768271890897138746582039089128053875620299138149315547875444447674573987934196165016" -string(313) "3168892355445512933444812965909472020409957119791476182178991646344151155563236535370283312345943041041662641584330401473731788344553589640556705580180081371688996848117690101021660395072221488243400947129794119144961728431002781350889740682623487619845390287149216977767858293453242551076767446272230208078076521" -string(469) "5641066640108537808257411937508162073054596465771071759059984994432846497317882144255197676537588304873835452821393566559424565939427398239568910381599042586683472720047480341060077571873252225062218300704671408283921205864218742798766467986541832811143938893251282757214673131758780892167922492222473153470483402146144945253685265421614344082690235633775622262137908096304889066587289890823326962594240368957840634699139830536223598719285051876381571976198029149478069" +string(2048) "7208f40638094224980892dbbc1492f40ee0fc3c80e47ee1f49813c31a0e9efc7ed333ade96d418d0109e770f34582da66d1aa48240a599e5fdba7616b3237b378a9d221b97812e21006e0d945ba1b24551370b0bbd8cc09109c1e018940f778a299251d2fcc0128023ed76d581d5822d49e2aad36f5df207126c640343d7e0628a1a607a277609f7913f8b626eff9eac072d4e1aaa8020a94aeafecdd450751c602bf34023217899b1308fe8b7292f0728c655fbe8216e7ec2208d555e7839ace169e352782a4bc8215ebd48609379eddd04ce53752717334c1bf465595bbf86382996776d182383e902da67f0524d29e0e758cb97758a1de50f2578bee7ed994ffcfd0d1df4e34cc3844208162b0f0a10236a554f4c6083c0d564e14efe8eef5e037d79c0c9d15e01c4ac69cbca71c7aeda729ee68b3d5289960b0ae6dc796db6542d2fdf607a2566633676067e70b32de7b7f48d3672c4bd44ade7b228c3044779014aa7d182ea3e6781e4d9a9c31acac7a5fb4109d0a2f47961555b8ef0101f43c7e0d65f7c6df480114e819ecbb2e708ad4c1da08a952935d1bf16d96d5d8753761214d8fcec8c088ca06dc181d227f126987d6b1d1f8be2f4843065e46aae233169d09ec1f96a5a553a15bfa76054bf4bf41ffbe23b7a70e47be5b976932b8c1194d94d789e50ca91b6fb68ef2d5997ebbe3d27c48bdabb44a0876711c291330e949e2bab052c59fbdb74abcb0cfbcc8c9b73002857b8fcf24135ab4aee95dbc1d2e66c1eb584c02f81701b01f08c51f0d9d8b665ea038726485ef6cd3e1fb6ede445ac1204146f280150e0bcff344a6babc7bbd73dcf00466f259b87c24f79e74613a17e265411722a68fc3b84f4afd8741701447f6132215662e7562a65b8cbca9011ad090993b1905fe845ba8595f13523e9ce5062a810338251ef9389504a8916f741bc0af914e61ac21b422fbb54f6dbf2adf5e06f88145e1aab7c7bf7cecbb4e116c038182956b4e5efc62d66f056fbb263a486a5a0974edd9833f08a95ae3c018332bd4b903642000931bb325bd86dbc6b212ee2dd87cdd4e20cba77822f01485624848efce7711802797d231c598aea1482d6685d1b6e4439ffdb54fc9ff1ba0c873a569abe9ff8ee07255654793d1c169bac0ed3f7c9b159348c989d6c10d8e3a5e4c206c6af22355531ee6903ef4db78bdb6ee7874f31932227d8e5f6b97e7158059b1853d90e15c5d733f3345e7ee11f8ac3e8d5dde9fd0397251826541ada4080ee7ff5d23f2486164b9e774896a80923e94ded1b221fe204bc7d0b2a0fbbdcd5b9ecdea449d5743030f5153f7e60b2e55e35fa9a7e0155737a1d39ee04696ea9de477f9e855f01bed483dcedecee7f59058f0a053c7301e11bb7689dd9f562e7fa799e8e62e2de97fcb838a29df790875769f1132c5e3" +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +string(389) "84916bf590f1bad61b6ede6cd6da703bca41cfb661c94b8cf66a1c92f0e2ebb24ad4683b908600ddf7145cac3b4808d6bbed18332d58d93c8ced3e0d3d19fd214a987f86116dd46c9709fd7d8a2b8ade79ba75e41df983b02082e89e3f729de3c6f42613a6b79b5e1967ab712e34cfb79e0d6f6168f7f758c2785da8ac1c36624fbb421a6502b2bbe9ad035c2577864aa12eee3173db7ffb915fce65a918041b95239d66d339de820a7d162cfccdfbd2222c91383ef0c4e903128cbd04dc0bf000000" diff --git a/ext/gmp/tests/gmp_cryptography_ecc.phpt b/ext/gmp/tests/gmp_cryptography_ecc.phpt new file mode 100644 index 0000000000000..900005b3334f5 --- /dev/null +++ b/ext/gmp/tests/gmp_cryptography_ecc.phpt @@ -0,0 +1,382 @@ +--TEST-- +Examples of the usage of gmp for elliptic curve cryptography. +--DESCRIPTION-- +DANGER: DO NOT USE IN SECURITY-RELATED USE-CASES. +This implementation is not hardened or tested against side channels (e.g. time or cache). +Side-channels as contained in this implementation may compromise secrets (e.g. secret keys). +Hence, it MUST NOT BE USED IN SECURITY-RELATED USE-CASES. + +This implementation operates on the secp256r1 curve from https://www.secg.org/sec2-v2.pdf (also known as NIST P-256). +For addition and doublication, it implements https://www.secg.org/sec1-v2.pdf (2.2.1). +For point decompression, it implements https://www.secg.org/sec1-v2.pdf (2.3.4). +For scalar multiplication, it uses the well-known double-add-always pardigm. + +The implementation executes a diffie-hellman handshake. +Omitted is an explicit demonstration of (public-key) encryption, commitments, zero-knowledge proofs or similar common applications. +However, the operations used for diffie-hellman is at the core of all these other applications, hence these use-cases are implicitly covered. + +$aliceSecret and $bobSecret generated with +$random = gmp_random_range(0, $n); +$randomHex = strtoupper(gmp_strval($random, 16)); +echo chunk_split($randomHex, 8, " "); +--EXTENSIONS-- +gmp +--FILE-- +x, 0) === 0 && gmp_cmp($this->y, 0) === 0; + } + + public function equals(self $other): bool + { + return gmp_cmp($this->x, $other->x) === 0 && gmp_cmp($this->y, $other->y) === 0; + } +} + + +/** + * In the finite field F_p, + * an elliptic curve in the short Weierstrass form y^2 = x^3 + ax + b is defined, + * forming a group over addition. + * + * A base point G of order n and cofactor h is picked in this group. + */ +class Curve +{ + public function __construct( + private readonly \GMP $p, + private readonly \GMP $a, + private readonly \GMP $b, + private readonly Point $G, + private readonly \GMP $n + ) {} + + public function getP(): \GMP + { + return $this->p; + } + + public function getA(): \GMP + { + return $this->a; + } + + public function getB(): \GMP + { + return $this->b; + } + + public function getG(): Point + { + return $this->G; + } + + public function getN(): \GMP + { + return $this->n; + } +} + + +/** + * Math inside a prime field; hence always (mod p) + */ +class PrimeField +{ + private int $elementBitLength; + + public function __construct(private readonly \GMP $prime) + { + $this->elementBitLength = strlen(gmp_strval($prime, 2)); + } + + public function getElementBitLength(): int + { + return $this->elementBitLength; + } + + public function add(\GMP $a, \GMP $b): \GMP + { + $r = gmp_add($a, $b); + return gmp_mod($r, $this->prime); + } + + public function mul(\GMP $a, \GMP $b): \GMP + { + $r = gmp_mul($a, $b); + return gmp_mod($r, $this->prime); + } + + public function sub(\GMP $a, \GMP $b): \GMP + { + $r = gmp_sub($a, $b); + return gmp_mod($r, $this->prime); + } + + public function mod(\GMP $a): \GMP + { + return gmp_mod($a, $this->prime); + } + + public function invert(\GMP $z): \GMP|false + { + return gmp_invert($z, $this->prime); + } +} + +class UnsafePrimeCurveMath +{ + private PrimeField $field; + public function __construct(private readonly Curve $curve) + { + $this->field = new PrimeField($this->curve->getP()); + } + + /** + * checks whether point fulfills the defining equation of the curve + */ + public function isOnCurve(Point $point): bool + { + $left = gmp_pow($point->y, 2); + $right = gmp_add( + gmp_add( + gmp_pow($point->x, 3), + gmp_mul($this->curve->getA(), $point->x) + ), + $this->curve->getB() + ); + + $comparison = $this->field->sub($left, $right); + + return gmp_cmp($comparison, 0) == 0; + } + + /** + * implements https://www.secg.org/sec1-v2.pdf 2.3.4 + */ + public function fromXCoordinate(\GMP $x, bool $isEvenY): Point + { + $alpha = gmp_add( + gmp_add( + gmp_powm($x, gmp_init(3, 10), $this->curve->getP()), + gmp_mul($this->curve->getA(), $x) + ), + $this->curve->getB() + ); + + $jacobiSymbol = gmp_jacobi($alpha, $this->curve->getP()); + if ($jacobiSymbol !== 1) { + throw new Exception('No square root of alpha.'); + } + + /* + * take the square root of alpha, while doing a (much cheaper) exponentiation + * + * observe that alpha^((p+1)/4) = y^((p+1)/2) = y^((p-1)/2) * y = y + * (p+1)/4 is an integer, as for our prime p it holds that p mod 4 = 3 + * alpha = y^2 by the jacobi symbol check above that asserts y is a quadratic residue + * y^((p-1)/2) = 1 by Euler's Criterion applies to the quadratic residue y + */ + $const = gmp_div(gmp_add($this->curve->getP(), 1), 4); + $beta = gmp_powm($alpha, $const, $this->curve->getP()); + + $yp = $isEvenY ? gmp_init(0) : gmp_init(1); + if (gmp_cmp(gmp_mod($beta, 2), $yp) === 0) { + return new Point($x, $beta); + } else { + return new Point($x, gmp_sub($this->curve->getP(), $beta)); + } + } + + /** + * rules from https://www.secg.org/SEC1-Ver-1.0.pdf (2.2.1) + */ + private function add(Point $a, Point $b): Point + { + // rule 1 & 2 + if ($a->isInfinity()) { + return clone $b; + } elseif ($b->isInfinity()) { + return clone $a; + } + + if (gmp_cmp($a->x, $b->x) === 0) { + // rule 3 + if (gmp_cmp($b->y, $a->y) !== 0) { + return Point::createInfinity(); + } + + // rule 5 + return $this->double($a); + } + + // rule 4 (note that a / b = a * b^-1) + $lambda = $this->field->mul( + gmp_sub($b->y, $a->y), + $this->field->invert(gmp_sub($b->x, $a->x)) + ); + + $x = $this->field->sub( + gmp_sub( + gmp_pow($lambda, 2), + $a->x + ), + $b->x + ); + + $y = $this->field->sub( + gmp_mul( + $lambda, + gmp_sub($a->x, $x) + ), + $a->y + ); + + return new Point($x, $y); + } + + private function double(Point $a): Point + { + if (gmp_cmp($a->y, 0) === 0) { + return Point::createInfinity(); + } + + // rule 5 (note that a / b = a * b^-1) + $lambda = $this->field->mul( + gmp_add( + gmp_mul( + gmp_init(3), + gmp_pow($a->x, 2) + ), + $this->curve->getA() + ), + $this->field->invert( + gmp_mul(2, $a->y) + ) + ); + + $x = $this->field->sub( + gmp_pow($lambda, 2), + gmp_mul(2, $a->x) + ); + + $y = $this->field->sub( + gmp_mul( + $lambda, + gmp_sub($a->x, $x) + ), + $a->y + ); + + return new Point($x, $y); + } + + private function conditionalSwap(Point $a, Point $b, int $swapBit): void + { + $this->conditionalSwapScalar($a->x, $b->x, $swapBit, $this->field->getElementBitLength()); + $this->conditionalSwapScalar($a->y, $b->y, $swapBit, $this->field->getElementBitLength()); + } + + private function conditionalSwapScalar(GMP &$a, GMP &$b, int $swapBit, int $elementBitLength): void + { + // create a mask (note how it inverts the maskbit) + $mask = gmp_init(str_repeat((string)(1 - $swapBit), $elementBitLength), 2); + + // if mask is 1, tempA = a, else temp = 0 + $tempA = gmp_and($a, $mask); + $tempB = gmp_and($b, $mask); + + $a = gmp_xor($tempB, gmp_xor($a, $b)); // if mask is 1, then b XOR a XOR b = a, else 0 XOR a XOR b = a XOR b + $b = gmp_xor($tempA, gmp_xor($a, $b)); // if mask is 1, then a XOR a XOR b = b, else 0 XOR a XOR b XOR b = a + $a = gmp_xor($tempB, gmp_xor($a, $b)); // if mask is 1, then b XOR a XOR b = a, else 0 XOR a XOR b XOR a = b + + // hence if mask is 1 (= inverse of $swapBit), then no swap, else swap + } + + /** + * multiplication using the double-add-always + */ + public function mul(Point $point, \GMP $factor): Point + { + $mulField = new PrimeField($this->curve->getN()); + + // reduce factor once to ensure it is within our curve N bit size (and reduce computational effort) + $reducedFactor = $mulField->mod($factor); + + // normalize to the element bit length to always execute the double-add loop a constant number of times + $factorBits = gmp_strval($reducedFactor, 2); + $normalizedFactorBits = str_pad($factorBits, $mulField->getElementBitLength(), '0', STR_PAD_LEFT); + + /** + * how this works: + * first, observe r[0] is infinity and r[1] our "real" point. + * r[0] and r[1] are swapped iff the corresponding bit in $factor is set to 1, + * hence if $j = 1, then the "real" point is added, else the "real" point is doubled + */ + /** @var Point[] $r */ + $r = [Point::createInfinity(), clone $point]; + for ($i = 0; $i < $mulField->getElementBitLength(); $i++) { + $j = (int)$normalizedFactorBits[$i]; + + $this->conditionalSwap($r[0], $r[1], $j ^ 1); + + $r[0] = $this->add($r[0], $r[1]); + $r[1] = $this->double($r[1]); + + $this->conditionalSwap($r[0], $r[1], $j ^ 1); + } + + return $r[0]; + } +} + +// secp256r1 curve from https://www.secg.org/sec2-v2.pdf (also known as NIST P-256). +$p = gmp_init('FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF', 16); +$a = gmp_init('FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFC', 16); +$b = gmp_init('5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604B', 16); + +$Gx = gmp_init('6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296', 16); +$Gy = gmp_init('4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE CBB64068 37BF51F5', 16); +$G = new Point($Gx, $Gy); + +$n = gmp_init('FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551', 16); +$curve = new Curve($p, $a, $b, $G, $n); +$math = new UnsafePrimeCurveMath($curve); +var_dump($math->isOnCurve($G)); // sanity check + +// do diffie hellman key exchange +$aliceSecret = gmp_init('1421B466 CB12D4F1 298CF525 DE823345 B81B861F 25B5AA7B E86869F9 697C13D', 16); +$bobSecret = gmp_init('3CFFD9D8 3D5EF967 3432932D D70EC213 8D559C30 7EFBCFF6 0EB96EAB F08B0CBA', 16); + +$alicePublicKey = $math->mul($curve->getG(), $aliceSecret); +$bobPublicKey = $math->mul($curve->getG(), $bobSecret); + +$bobPublicKeyReconstructed = $math->fromXCoordinate($bobPublicKey->x, gmp_cmp(gmp_mod($bobPublicKey->y, 2), 0) === 0); +$aliceSharedKey = $math->mul($bobPublicKey, $aliceSecret); + +$alicePublicKeyReconstructed = $math->fromXCoordinate($alicePublicKey->x, gmp_cmp(gmp_mod($alicePublicKey->y, 2), 0) === 0); +$bobSharedKey = $math->mul($alicePublicKey, $bobSecret); + +var_dump($aliceSharedKey->equals($bobSharedKey)); +var_dump(gmp_strval($aliceSharedKey->x, 16)); +?> +--EXPECT-- +bool(true) +bool(true) +string(64) "f480daf4f56a674c16944cda9e7c9fd0ab2813eae3a5935bf9e091cadb5c9ac3" diff --git a/ext/gmp/tests/gmp_cryptography_overload_operators.phpt b/ext/gmp/tests/gmp_cryptography_overload_operators.phpt new file mode 100644 index 0000000000000..7f387e0fbc3c0 --- /dev/null +++ b/ext/gmp/tests/gmp_cryptography_overload_operators.phpt @@ -0,0 +1,112 @@ +--TEST-- +test operations done in finite field and elliptic curve cryptography, using operator overloads. (GH-16870) +--DESCRIPTION-- +Test overload operators of gmp with number sizes useful in cryptography. +It has the same content as `gmp_cryptography.phpt`, to which we refer for motivation of the operations. + +The only difference in this file is that whenever possible operator overloads are used. +The reason is that while fixing GH-16870, it was noticed that the overload operators and the functions evolved independently. +--EXTENSIONS-- +gmp +--FILE-- + 0); + + +// prime and b of secp521r1 from https://www.secg.org/sec2-v2.pdf +$p = gmp_init('01FF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF +FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF +FFFFFFFF FFFFFFFF FFFFFFFF', 16); +$b = gmp_init('0051 953EB961 8E1C9A1F 929A21A0 B68540EE A2DA725B 99B315F3 +B8B48991 8EF109E1 56193951 EC7E937B 1652C0BD 3BB1BF07 3573DF88 +3D2C34F1 EF451FD4 6B503F00', 16); + +$jacobi = gmp_jacobi($b, $p); +var_dump($jacobi === 1); + +$result = $p & $b; +var_dump(gmp_cmp($result, $b) === 0); + +$result = $p ^ $p; +var_dump(gmp_cmp($result, 0) === 0); + +$result = $b ** 3; +var_dump(gmp_strval($result, 16)); + +?> +--EXPECT-- +string(2048) "7208f40638094224980892dbbc1492f40ee0fc3c80e47ee1f49813c31a0e9efc7ed333ade96d418d0109e770f34582da66d1aa48240a599e5fdba7616b3237b378a9d221b97812e21006e0d945ba1b24551370b0bbd8cc09109c1e018940f778a299251d2fcc0128023ed76d581d5822d49e2aad36f5df207126c640343d7e0628a1a607a277609f7913f8b626eff9eac072d4e1aaa8020a94aeafecdd450751c602bf34023217899b1308fe8b7292f0728c655fbe8216e7ec2208d555e7839ace169e352782a4bc8215ebd48609379eddd04ce53752717334c1bf465595bbf86382996776d182383e902da67f0524d29e0e758cb97758a1de50f2578bee7ed994ffcfd0d1df4e34cc3844208162b0f0a10236a554f4c6083c0d564e14efe8eef5e037d79c0c9d15e01c4ac69cbca71c7aeda729ee68b3d5289960b0ae6dc796db6542d2fdf607a2566633676067e70b32de7b7f48d3672c4bd44ade7b228c3044779014aa7d182ea3e6781e4d9a9c31acac7a5fb4109d0a2f47961555b8ef0101f43c7e0d65f7c6df480114e819ecbb2e708ad4c1da08a952935d1bf16d96d5d8753761214d8fcec8c088ca06dc181d227f126987d6b1d1f8be2f4843065e46aae233169d09ec1f96a5a553a15bfa76054bf4bf41ffbe23b7a70e47be5b976932b8c1194d94d789e50ca91b6fb68ef2d5997ebbe3d27c48bdabb44a0876711c291330e949e2bab052c59fbdb74abcb0cfbcc8c9b73002857b8fcf24135ab4aee95dbc1d2e66c1eb584c02f81701b01f08c51f0d9d8b665ea038726485ef6cd3e1fb6ede445ac1204146f280150e0bcff344a6babc7bbd73dcf00466f259b87c24f79e74613a17e265411722a68fc3b84f4afd8741701447f6132215662e7562a65b8cbca9011ad090993b1905fe845ba8595f13523e9ce5062a810338251ef9389504a8916f741bc0af914e61ac21b422fbb54f6dbf2adf5e06f88145e1aab7c7bf7cecbb4e116c038182956b4e5efc62d66f056fbb263a486a5a0974edd9833f08a95ae3c018332bd4b903642000931bb325bd86dbc6b212ee2dd87cdd4e20cba77822f01485624848efce7711802797d231c598aea1482d6685d1b6e4439ffdb54fc9ff1ba0c873a569abe9ff8ee07255654793d1c169bac0ed3f7c9b159348c989d6c10d8e3a5e4c206c6af22355531ee6903ef4db78bdb6ee7874f31932227d8e5f6b97e7158059b1853d90e15c5d733f3345e7ee11f8ac3e8d5dde9fd0397251826541ada4080ee7ff5d23f2486164b9e774896a80923e94ded1b221fe204bc7d0b2a0fbbdcd5b9ecdea449d5743030f5153f7e60b2e55e35fa9a7e0155737a1d39ee04696ea9de477f9e855f01bed483dcedecee7f59058f0a053c7301e11bb7689dd9f562e7fa799e8e62e2de97fcb838a29df790875769f1132c5e3" +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +string(389) "84916bf590f1bad61b6ede6cd6da703bca41cfb661c94b8cf66a1c92f0e2ebb24ad4683b908600ddf7145cac3b4808d6bbed18332d58d93c8ced3e0d3d19fd214a987f86116dd46c9709fd7d8a2b8ade79ba75e41df983b02082e89e3f729de3c6f42613a6b79b5e1967ab712e34cfb79e0d6f6168f7f758c2785da8ac1c36624fbb421a6502b2bbe9ad035c2577864aa12eee3173db7ffb915fce65a918041b95239d66d339de820a7d162cfccdfbd2222c91383ef0c4e903128cbd04dc0bf000000" From be53902a13dbbd59ed3b6f691c4def17f25e5f22 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 5 May 2025 14:40:09 +0100 Subject: [PATCH 470/503] ext/pgsql: globals data struct rework/size reduction (#18503) --- ext/pgsql/php_pgsql.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h index 75979b5e80fca..7a5770cb59369 100644 --- a/ext/pgsql/php_pgsql.h +++ b/ext/pgsql/php_pgsql.h @@ -180,12 +180,12 @@ static const php_stream_ops php_stream_pgsql_fd_ops = { ZEND_BEGIN_MODULE_GLOBALS(pgsql) zend_long num_links,num_persistent; zend_long max_links,max_persistent; - bool allow_persistent; - int ignore_notices; zend_long auto_reset_persistent; - int log_notices; zend_object *default_link; /* default link when connection is omitted */ zend_string *regexes[PGSQL_MAX_REGEXES]; + bool allow_persistent; + bool ignore_notices; + bool log_notices; HashTable field_oids; HashTable table_oids; HashTable connections; From a9b84f942599ab0fb31f36c09128f67686baa341 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 5 May 2025 19:12:39 +0200 Subject: [PATCH 471/503] Use specialized functions/macros to reduce code size in ext/random (#18499) On x86-64 with GCC 14.2.1: zim_Random_Randomizer_getBytes goes from 514 to 418 bytes zim_Random_Randomizer_getBytesFromString goes from 750 to 676 bytes --- ext/random/randomizer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 0585ea95e668e..4f63388e8f56a 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -297,7 +297,7 @@ PHP_METHOD(Random_Randomizer, getBytes) while (total_size + 8 <= length) { result = engine.algo->generate(engine.state); if (EG(exception)) { - zend_string_free(retval); + zend_string_efree(retval); RETURN_THROWS(); } @@ -326,7 +326,7 @@ PHP_METHOD(Random_Randomizer, getBytes) while (total_size < length) { result = engine.algo->generate(engine.state); if (EG(exception)) { - zend_string_free(retval); + zend_string_efree(retval); RETURN_THROWS(); } @@ -342,7 +342,7 @@ PHP_METHOD(Random_Randomizer, getBytes) } ZSTR_VAL(retval)[length] = '\0'; - RETURN_STR(retval); + RETURN_NEW_STR(retval); } /* }}} */ @@ -451,7 +451,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString) uint64_t offset = engine.algo->range(engine.state, 0, max_offset); if (EG(exception)) { - zend_string_free(retval); + zend_string_efree(retval); RETURN_THROWS(); } @@ -473,7 +473,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString) while (total_size < length) { php_random_result result = engine.algo->generate(engine.state); if (EG(exception)) { - zend_string_free(retval); + zend_string_efree(retval); RETURN_THROWS(); } @@ -484,7 +484,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString) if (offset > max_offset) { if (++failures > PHP_RANDOM_RANGE_ATTEMPTS) { - zend_string_free(retval); + zend_string_efree(retval); zend_throw_error(random_ce_Random_BrokenRandomEngineError, "Failed to generate an acceptable random number in %d attempts", PHP_RANDOM_RANGE_ATTEMPTS); RETURN_THROWS(); } @@ -503,7 +503,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString) } ZSTR_VAL(retval)[length] = '\0'; - RETURN_STR(retval); + RETURN_NEW_STR(retval); } /* }}} */ From fb3536fd60d8264a7226db765ea5d8153a8b0864 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 2 Apr 2025 20:11:12 +0200 Subject: [PATCH 472/503] Fix leak+crash with sapi_windows_set_ctrl_handler() The ctrl_handler is never destroyed. We have to destroy it at request end so we avoid leaking it and also avoid keeping a reference to previous request memory in a next request. The latter can result in a crash and can be demonstrated with this script and `--repeat 2`: ```php class Test { public function set() { sapi_windows_set_ctrl_handler(self::cb(...)); } public function cb() { } } $test = new Test; $test->set(); sleep(3); ``` When you hit CTRL+C in the second request you can crash. This patch resolves both the leak and crash by destroying the ctrl_handler after a request. Closes GH-18231. --- NEWS | 3 ++ .../sapi_windows_set_ctrl_handler_leak.phpt | 28 +++++++++++++++++++ win32/globals.c | 2 ++ win32/signal.c | 23 +++++++++++++-- win32/signal.h | 1 + 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 sapi/cli/tests/sapi_windows_set_ctrl_handler_leak.phpt diff --git a/NEWS b/NEWS index ed6cd4e2e3a57..66301a388ce28 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,9 @@ PHP NEWS - Standard: . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) +- Windows: + . Fix leak+crash with sapi_windows_set_ctrl_handler(). (nielsdos) + - Zip: . Fixed bug GH-18431 (Registering ZIP progress callback twice doesn't work). (nielsdos) diff --git a/sapi/cli/tests/sapi_windows_set_ctrl_handler_leak.phpt b/sapi/cli/tests/sapi_windows_set_ctrl_handler_leak.phpt new file mode 100644 index 0000000000000..e91b6c63c344f --- /dev/null +++ b/sapi/cli/tests/sapi_windows_set_ctrl_handler_leak.phpt @@ -0,0 +1,28 @@ +--TEST-- +sapi_windows_set_ctrl_handler() leak bug +--SKIPIF-- + +--FILE-- +set(); + +echo "Done\n"; + +?> +--EXPECT-- +Done diff --git a/win32/globals.c b/win32/globals.c index b2889c77e9cef..3f35249057328 100644 --- a/win32/globals.c +++ b/win32/globals.c @@ -63,5 +63,7 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals) {/*{{{*/ closelog(); + php_win32_signal_ctrl_handler_request_shutdown(); + return SUCCESS; }/*}}}*/ diff --git a/win32/signal.c b/win32/signal.c index 1207fe1fc092f..21b855f02ea2a 100644 --- a/win32/signal.c +++ b/win32/signal.c @@ -68,9 +68,28 @@ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_shutdown(void) zend_interrupt_function = orig_interrupt_function; orig_interrupt_function = NULL; vm_interrupt_flag = NULL; - ZVAL_UNDEF(&ctrl_handler); }/*}}}*/ +PHP_WINUTIL_API void php_win32_signal_ctrl_handler_request_shutdown(void) +{ + /* Must be initialized and in main thread */ + if (!vm_interrupt_flag) { + return; + } +#ifdef ZTS + if (!tsrm_is_main_thread()) { + return; + } +#endif + + /* The ctrl_handler must be cleared between requests, otherwise we can crash + * due to accessing a previous request's memory. */ + if (!Z_ISUNDEF(ctrl_handler)) { + zval_ptr_dtor(&ctrl_handler); + ZVAL_UNDEF(&ctrl_handler); + } +} + static BOOL WINAPI php_win32_signal_system_ctrl_handler(DWORD evt) {/*{{{*/ if (CTRL_C_EVENT != evt && CTRL_BREAK_EVENT != evt) { @@ -125,7 +144,7 @@ PHP_FUNCTION(sapi_windows_set_ctrl_handler) RETURN_FALSE; } - zval_ptr_dtor_nogc(&ctrl_handler); + zval_ptr_dtor(&ctrl_handler); ZVAL_COPY(&ctrl_handler, &fci.function_name); RETURN_TRUE; diff --git a/win32/signal.h b/win32/signal.h index 2058dd873b075..d7048d96a0a6c 100644 --- a/win32/signal.h +++ b/win32/signal.h @@ -10,6 +10,7 @@ #define SIGPROF 27 /* profiling time alarm */ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_init(void); +PHP_WINUTIL_API void php_win32_signal_ctrl_handler_request_shutdown(void); PHP_WINUTIL_API void php_win32_signal_ctrl_handler_shutdown(void); #endif /* PHP_WIN32_SIGNAL_H */ From dcf9d8f812abb3854c802e4b831d82f9d7e5c26f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 4 May 2025 19:09:05 +0200 Subject: [PATCH 473/503] Fix GH-18494: PDO OCI segfault in statement GC This is the same issue that was fixed in 2ae897fff7af3a794a31a8aeeeeb4f21f6a41393, but now for OCI. Closes GH-18495. --- NEWS | 3 +++ ext/pdo_oci/oci_statement.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 66301a388ce28..15b8fa714223b 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,9 @@ PHP NEWS . Fixed bug GH-18417 (Windows SHM reattachment fails when increasing memory_consumption or jit_buffer_size). (nielsdos) +- PDO_OCI: + . Fixed bug GH-18494 (PDO OCI segfault in statement GC). (nielsdos) + - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). (nielsdos) diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c index f3be69f9c32c2..f91b27975e88e 100644 --- a/ext/pdo_oci/oci_statement.c +++ b/ext/pdo_oci/oci_statement.c @@ -98,14 +98,21 @@ static int oci_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */ S->einfo.errmsg = NULL; } + /* TODO: There's php_pdo_stmt_valid_db_obj_handle in PHP-8.5-dev that does these checks. */ + bool server_obj_usable = !Z_ISUNDEF(stmt->database_object_handle) + && IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) + && !(OBJ_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED); + if (S->cols) { for (i = 0; i < stmt->column_count; i++) { if (S->cols[i].data) { switch (S->cols[i].dtype) { case SQLT_BLOB: case SQLT_CLOB: - OCI_TEMPLOB_CLOSE(S->H->env, S->H->svc, S->H->err, - (OCILobLocator *) S->cols[i].data); + if (server_obj_usable) { + OCI_TEMPLOB_CLOSE(S->H->env, S->H->svc, S->H->err, + (OCILobLocator *) S->cols[i].data); + } OCIDescriptorFree(S->cols[i].data, OCI_DTYPE_LOB); break; default: From 69f0882d3be713ede475addf11c79aa7542c9de2 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 6 May 2025 14:34:07 +0200 Subject: [PATCH 474/503] Fix missing include in win32/globals.c This previously errored with: win32\globals.c(66): error C2220: the following warning is treated as an error win32\globals.c(66): warning C4013: 'php_win32_signal_ctrl_handler_request_shutdown' undefined; assuming extern returning int This only errors on master because of 2473f57ba (thanks to Niels for that info!). Closes GH-18508 --- win32/globals.c | 1 + 1 file changed, 1 insertion(+) diff --git a/win32/globals.c b/win32/globals.c index 3f35249057328..13760cb1cb564 100644 --- a/win32/globals.c +++ b/win32/globals.c @@ -17,6 +17,7 @@ #include "php.h" #include "php_win32_globals.h" #include "syslog.h" +#include "signal.h" #ifdef ZTS PHPAPI int php_win32_core_globals_id; From cb4bafa4c0c108a3e142730042f2029130d0340b Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 6 May 2025 19:14:55 +0100 Subject: [PATCH 475/503] Init OpenSSL libctx and use it for pkey (#18282) --- ext/openssl/openssl.c | 14 +++++--- ext/openssl/openssl_backend_common.c | 46 +++++++++++++++++++++----- ext/openssl/openssl_backend_v1.c | 10 ++++++ ext/openssl/openssl_backend_v3.c | 48 ++++++++++++++++++++++------ ext/openssl/php_openssl.h | 4 +++ ext/openssl/php_openssl_backend.h | 14 +++++--- 6 files changed, 111 insertions(+), 25 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index b17159d46aabc..aab240dc8506a 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -438,6 +438,9 @@ PHP_GINIT_FUNCTION(openssl) #endif openssl_globals->errors = NULL; openssl_globals->errors_mark = NULL; +#if PHP_OPENSSL_API_VERSION >= 0x30000 + php_openssl_backend_init_libctx(&openssl_globals->libctx, &openssl_globals->propq); +#endif } /* }}} */ @@ -450,6 +453,9 @@ PHP_GSHUTDOWN_FUNCTION(openssl) if (openssl_globals->errors_mark) { pefree(openssl_globals->errors_mark, 1); } +#if PHP_OPENSSL_API_VERSION >= 0x30000 + php_openssl_backend_destroy_libctx(openssl_globals->libctx, openssl_globals->propq); +#endif } /* }}} */ @@ -2036,19 +2042,19 @@ PHP_FUNCTION(openssl_pkey_new) #if PHP_OPENSSL_API_VERSION >= 0x30000 } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x25519", sizeof("x25519") - 1)) != NULL && Z_TYPE_P(data) == IS_ARRAY) { - php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X25519, data); + php_openssl_pkey_object_curve_25519_448(return_value, "X25519", data); return; } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed25519", sizeof("ed25519") - 1)) != NULL && Z_TYPE_P(data) == IS_ARRAY) { - php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED25519, data); + php_openssl_pkey_object_curve_25519_448(return_value, "ED25519", data); return; } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x448", sizeof("x448") - 1)) != NULL && Z_TYPE_P(data) == IS_ARRAY) { - php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X448, data); + php_openssl_pkey_object_curve_25519_448(return_value, "X448", data); return; } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed448", sizeof("ed448") - 1)) != NULL && Z_TYPE_P(data) == IS_ARRAY) { - php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED448, data); + php_openssl_pkey_object_curve_25519_448(return_value, "ED448", data); return; #endif } diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c index 44cb22e18d2ab..0cda27407a567 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -1244,9 +1244,7 @@ EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key) return pub_key; } - -/* {{{ php_openssl_pem_password_cb */ -int php_openssl_pem_password_cb(char *buf, int size, int rwflag, void *userdata) +static int php_openssl_pem_password_cb(char *buf, int size, int rwflag, void *userdata) { struct php_openssl_pem_password *password = userdata; @@ -1429,7 +1427,7 @@ EVP_PKEY *php_openssl_pkey_from_zval( zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size) { - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_pkey(key); if (!ctx) { return NULL; } @@ -1456,7 +1454,7 @@ zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t k return result; } -int php_openssl_get_evp_pkey_type(int key_type) { +static int php_openssl_get_evp_pkey_type(int key_type) { switch (key_type) { case OPENSSL_KEYTYPE_RSA: return EVP_PKEY_RSA; @@ -1487,7 +1485,38 @@ int php_openssl_get_evp_pkey_type(int key_type) { } } -EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) +static const char *php_openssl_get_evp_pkey_name(int key_type) { + switch (key_type) { + case OPENSSL_KEYTYPE_RSA: + return "RSA"; +#if !defined(OPENSSL_NO_DSA) + case OPENSSL_KEYTYPE_DSA: + return "DSA"; +#endif +#if !defined(NO_DH) + case OPENSSL_KEYTYPE_DH: + return "DH"; +#endif +#ifdef HAVE_EVP_PKEY_EC + case OPENSSL_KEYTYPE_EC: + return "EC"; +#endif +#if PHP_OPENSSL_API_VERSION >= 0x30000 + case OPENSSL_KEYTYPE_X25519: + return "X25519"; + case OPENSSL_KEYTYPE_ED25519: + return "ED25519"; + case OPENSSL_KEYTYPE_X448: + return "X448"; + case OPENSSL_KEYTYPE_ED448: + return "ED448"; +#endif + default: + return ""; + } +} + +EVP_PKEY *php_openssl_generate_private_key(struct php_x509_request * req) { if (req->priv_key_bits < MIN_KEY_LENGTH) { php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d", @@ -1500,6 +1529,7 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) php_error_docref(NULL, E_WARNING, "Unsupported private key type"); return NULL; } + const char *name = php_openssl_get_evp_pkey_name(req->priv_key_type); int egdsocket, seeded; char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE"); @@ -1507,7 +1537,7 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) EVP_PKEY *key = NULL; EVP_PKEY *params = NULL; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name(name, type); if (!ctx) { php_openssl_store_errors(); goto cleanup; @@ -1569,7 +1599,7 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) } EVP_PKEY_CTX_free(ctx); - ctx = EVP_PKEY_CTX_new(params, NULL); + ctx = php_openssl_pkey_new_from_pkey(params); if (!ctx) { php_openssl_store_errors(); goto cleanup; diff --git a/ext/openssl/openssl_backend_v1.c b/ext/openssl/openssl_backend_v1.c index 59988451bbbd0..eb94ee3fbe4bc 100644 --- a/ext/openssl/openssl_backend_v1.c +++ b/ext/openssl/openssl_backend_v1.c @@ -44,6 +44,16 @@ void php_openssl_backend_shutdown(void) #endif } +EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id) +{ + return EVP_PKEY_CTX_new_id(id, NULL); +} + +EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey) +{ + return EVP_PKEY_CTX_new(pkey, NULL); +} + static bool php_openssl_pkey_init_rsa_data(RSA *rsa, zval *data) { BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; diff --git a/ext/openssl/openssl_backend_v3.c b/ext/openssl/openssl_backend_v3.c index 76965d66e65a7..0876690aee0ba 100644 --- a/ext/openssl/openssl_backend_v3.c +++ b/ext/openssl/openssl_backend_v3.c @@ -22,17 +22,47 @@ #include #include +ZEND_EXTERN_MODULE_GLOBALS(openssl) + void php_openssl_backend_shutdown(void) { (void) 0; } +void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq) +{ + /* The return value is not checked because we cannot reasonable fail in GINIT so using NULL + * (default context) is probably better. */ + *plibctx = OSSL_LIB_CTX_new(); + *ppropq = NULL; +} + +void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq) +{ + if (libctx != NULL) { + OSSL_LIB_CTX_free(libctx); + } + if (propq != NULL) { + free(propq); + } +} + +EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id) +{ + return EVP_PKEY_CTX_new_from_name(OPENSSL_G(libctx), name, OPENSSL_G(propq)); +} + +EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey) +{ + return EVP_PKEY_CTX_new_from_pkey(OPENSSL_G(libctx), pkey, OPENSSL_G(propq)); +} + EVP_PKEY *php_openssl_pkey_init_rsa(zval *data) { BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; EVP_PKEY *pkey = NULL; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("RSA", EVP_PKEY_RSA); OSSL_PARAM *params = NULL; OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); @@ -100,7 +130,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private) { BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; EVP_PKEY *param_key = NULL, *pkey = NULL; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DSA", EVP_PKEY_DSA); OSSL_PARAM *params = NULL; OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); @@ -144,7 +174,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private) } else { *is_private = true; EVP_PKEY_CTX_free(ctx); - ctx = EVP_PKEY_CTX_new(param_key, NULL); + ctx = php_openssl_pkey_new_from_pkey(param_key); if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { goto cleanup; } @@ -168,7 +198,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private) { BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; EVP_PKEY *param_key = NULL, *pkey = NULL; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DH", EVP_PKEY_DH); OSSL_PARAM *params = NULL; OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); @@ -219,7 +249,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private) } else { *is_private = true; EVP_PKEY_CTX_free(ctx); - ctx = EVP_PKEY_CTX_new(param_key, NULL); + ctx = php_openssl_pkey_new_from_pkey(param_key); if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { goto cleanup; } @@ -250,7 +280,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { unsigned char *point_q_buf = NULL; EC_GROUP *group = NULL; EVP_PKEY *param_key = NULL, *pkey = NULL; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("EC", EVP_PKEY_EC); BN_CTX *bctx = BN_CTX_new(); OSSL_PARAM *params = NULL; OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); @@ -269,7 +299,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { goto cleanup; } - if (!(group = EC_GROUP_new_by_curve_name(nid))) { + if (!(group = EC_GROUP_new_by_curve_name_ex(OPENSSL_G(libctx), OPENSSL_G(propq), nid))) { goto cleanup; } @@ -438,7 +468,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { } #endif -void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data) { +void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; OSSL_PARAM *params = NULL; @@ -466,7 +496,7 @@ void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, z } params = OSSL_PARAM_BLD_to_param(bld); - ctx = EVP_PKEY_CTX_new_id(key_type, NULL); + ctx = php_openssl_pkey_new_from_name(name, 0); if (!params || !ctx) { goto cleanup; } diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index bc101539d1b1e..67522f3d34717 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -73,6 +73,10 @@ struct php_openssl_errors { ZEND_BEGIN_MODULE_GLOBALS(openssl) struct php_openssl_errors *errors; struct php_openssl_errors *errors_mark; +#if PHP_OPENSSL_API_VERSION >= 0x30000 + OSSL_LIB_CTX *libctx; + char *propq; +#endif ZEND_END_MODULE_GLOBALS(openssl) #define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v) diff --git a/ext/openssl/php_openssl_backend.h b/ext/openssl/php_openssl_backend.h index 158b4e27712f9..5cfa73160b853 100644 --- a/ext/openssl/php_openssl_backend.h +++ b/ext/openssl/php_openssl_backend.h @@ -225,8 +225,15 @@ EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo); const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo); void php_openssl_backend_init(void); +void php_openssl_backend_init_common(void); +void php_openssl_backend_gshutdown(void); void php_openssl_backend_shutdown(void); +#if PHP_OPENSSL_API_VERSION >= 0x30000 +void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq); +void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq); +#endif + const char *php_openssl_get_conf_filename(void); void php_openssl_set_cert_locations(zval *return_value); @@ -273,10 +280,8 @@ struct php_openssl_pem_password { int len; }; -int php_openssl_pem_password_cb(char *buf, int size, int rwflag, void *userdata); EVP_PKEY *php_openssl_pkey_from_zval( zval *val, int public_key, char *passphrase, size_t passphrase_len, uint32_t arg_num); -int php_openssl_get_evp_pkey_type(int key_type); EVP_PKEY *php_openssl_generate_private_key(struct php_x509_request * req); void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char *name); @@ -296,15 +301,16 @@ void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char *name); } \ } while (0); +EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id); +EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey); EVP_PKEY *php_openssl_pkey_init_rsa(zval *data); EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private); BIGNUM *php_openssl_dh_pub_from_priv(BIGNUM *priv_key, BIGNUM *g, BIGNUM *p); EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private); EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private); -void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data); #if PHP_OPENSSL_API_VERSION >= 0x30000 -void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data); +void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data); #endif zend_long php_openssl_pkey_get_details(zval *return_value, EVP_PKEY *pkey); From e7a44a68e90018efaff0c8045fd0c9290140a7b5 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 6 May 2025 22:05:27 +0200 Subject: [PATCH 476/503] Sync EXTENSIONS and extend maintenance time --- EXTENSIONS | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/EXTENSIONS b/EXTENSIONS index 3ce5144b26554..7f23894e17e82 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -181,49 +181,56 @@ EXTENSION: dom PRIMARY MAINTAINER: Christian Stocker (2003 - 2011) Rob Richards (2003 - 2012) Marcus Börger (2003 - 2006) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 5.0 ------------------------------------------------------------------------------- EXTENSION: simplexml PRIMARY MAINTAINER: Marcus Börger (2003 - 2008) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 5.0 ------------------------------------------------------------------------------- EXTENSION: soap PRIMARY MAINTAINER: Dmitry Stogov (2004 - 2018) - Niels Dossche (2024 - 2024) + Niels Dossche (2024 - 2025) MAINTENANCE: Odd fixes STATUS: Working ------------------------------------------------------------------------------- EXTENSION: xml PRIMARY MAINTAINER: Thies C. Arntzen (1999 - 2002) Rob Richards (2003 - 2013) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- EXTENSION: libxml PRIMARY MAINTAINER: Rob Richards (2003 - 2009) Christian Stocker (2004 - 2011) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- EXTENSION: xmlreader PRIMARY MAINTAINER: Rob Richards (2004 - 2010) Christian Stocker (2004 - 2004) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- EXTENSION: xmlwriter PRIMARY MAINTAINER: Rob Richards (2004 - 2010) Pierre-Alain Joye (2005-2009) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- EXTENSION: xsl PRIMARY MAINTAINER: Christian Stocker (2003 - 2011) Rob Richards (2003 - 2010) + Niels Dossche (2023 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 5.0 From 168343d2e811fe0f2152d39a8f88557cc0b35c86 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 7 May 2025 08:15:50 +0200 Subject: [PATCH 477/503] [RFC] Implement array_first() and array_last() (#18210) --- NEWS | 1 + UPGRADING | 4 ++ ext/standard/array.c | 26 +++++++++ ext/standard/basic_functions.stub.php | 10 ++++ ext/standard/basic_functions_arginfo.h | 12 ++++- .../tests/array/array_first_last.phpt | 53 +++++++++++++++++++ .../tests/array/array_first_last_errors.phpt | 20 +++++++ 7 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/array/array_first_last.phpt create mode 100644 ext/standard/tests/array/array_first_last_errors.phpt diff --git a/NEWS b/NEWS index 98f8efa4fadfd..706533b9c898a 100644 --- a/NEWS +++ b/NEWS @@ -211,6 +211,7 @@ PHP NEWS (Michael Orlitzky). . Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first class callables returns wrong name). (timwolla) + . Added array_first() and array_last(). (nielsdos) - Streams: . Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows). diff --git a/UPGRADING b/UPGRADING index 04bc66c4890c4..6000c237f85d0 100644 --- a/UPGRADING +++ b/UPGRADING @@ -356,6 +356,10 @@ PHP 8.5 UPGRADE NOTES . ReflectionConstant::getAttributes() was introduced. RFC: https://wiki.php.net/rfc/attributes-on-constants +- Standard: + . Added array_first() and array_last(). + RFC: https://wiki.php.net/rfc/array_first_last + ======================================== 7. New Classes and Interfaces ======================================== diff --git a/ext/standard/array.c b/ext/standard/array.c index 6fe91fb714915..522e7f715acb7 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4513,6 +4513,32 @@ PHP_FUNCTION(array_key_last) } /* }}} */ +PHP_FUNCTION(array_first) +{ + HashTable *array; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(array) + ZEND_PARSE_PARAMETERS_END(); + + ZEND_HASH_FOREACH_VAL(array, zval *zv) { + RETURN_COPY_DEREF(zv); + } ZEND_HASH_FOREACH_END(); +} + +PHP_FUNCTION(array_last) +{ + HashTable *array; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(array) + ZEND_PARSE_PARAMETERS_END(); + + ZEND_HASH_REVERSE_FOREACH_VAL(array, zval *zv) { + RETURN_COPY_DEREF(zv); + } ZEND_HASH_FOREACH_END(); +} + /* {{{ Return just the values from the input array */ PHP_FUNCTION(array_values) { diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index e7f4ff8844714..4bec9d07348c0 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1712,6 +1712,16 @@ function array_key_first(array $array): int|string|null {} */ function array_key_last(array $array): int|string|null {} +/** + * @compile-time-eval + */ +function array_first(array $array): mixed {} + +/** + * @compile-time-eval + */ +function array_last(array $array): mixed {} + /** * @return array * @compile-time-eval diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 3d92288643159..c39ddafc827ec 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 85677dc3476d25b7820fd3a26fe39f2e9378b6e7 */ + * Stub hash: f1fdd58097ccd7562c63aee8e9cc1ca88f5bdf31 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -235,6 +235,12 @@ ZEND_END_ARG_INFO() #define arginfo_array_key_last arginfo_array_key_first +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_first, 0, 1, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +#define arginfo_array_last arginfo_array_first + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_values, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -2350,6 +2356,8 @@ ZEND_FUNCTION(array_replace_recursive); ZEND_FUNCTION(array_keys); ZEND_FUNCTION(array_key_first); ZEND_FUNCTION(array_key_last); +ZEND_FUNCTION(array_first); +ZEND_FUNCTION(array_last); ZEND_FUNCTION(array_values); ZEND_FUNCTION(array_count_values); ZEND_FUNCTION(array_column); @@ -2943,6 +2951,8 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("array_keys", zif_array_keys, arginfo_array_keys, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("array_key_first", zif_array_key_first, arginfo_array_key_first, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("array_key_last", zif_array_key_last, arginfo_array_key_last, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("array_first", zif_array_first, arginfo_array_first, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("array_last", zif_array_last, arginfo_array_last, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("array_values", zif_array_values, arginfo_array_values, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("array_count_values", zif_array_count_values, arginfo_array_count_values, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("array_column", zif_array_column, arginfo_array_column, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) diff --git a/ext/standard/tests/array/array_first_last.phpt b/ext/standard/tests/array/array_first_last.phpt new file mode 100644 index 0000000000000..f8f7a6afc3624 --- /dev/null +++ b/ext/standard/tests/array/array_first_last.phpt @@ -0,0 +1,53 @@ +--TEST-- +array_first()/array_last() +--FILE-- + 1, 0 => 0, 3 => 3, 2 => 2], + [100 => []], + [new stdClass, false], + [true, new stdClass], +]; + +foreach ($test_cases as $test_case) { + // Output the checked values + echo "--- Testing: ", json_encode($test_case), " ---\n"; + echo "First: ", json_encode(array_first($test_case)), "\n"; + echo "Last: ", json_encode(array_last($test_case)), "\n"; + + // Sanity check consistency with array_key_first()/array_key_last() + if (array_first($test_case) !== $test_case[array_key_first($test_case)]) { + throw new Error("Key first and value first inconsistency"); + } + if (array_last($test_case) !== $test_case[array_key_last($test_case)]) { + throw new Error("Key last and value last inconsistency"); + } +} +?> +--EXPECT-- +--- Testing: ["single element"] --- +First: "single element" +Last: "single element" +--- Testing: ["hello world",1] --- +First: "hello world" +Last: 1 +--- Testing: [1,"hello world"] --- +First: 1 +Last: "hello world" +--- Testing: {"1":1,"0":0,"3":3,"2":2} --- +First: 1 +Last: 2 +--- Testing: {"100":[]} --- +First: [] +Last: [] +--- Testing: [{},false] --- +First: {} +Last: false +--- Testing: [true,{}] --- +First: true +Last: {} diff --git a/ext/standard/tests/array/array_first_last_errors.phpt b/ext/standard/tests/array/array_first_last_errors.phpt new file mode 100644 index 0000000000000..4225bf8289198 --- /dev/null +++ b/ext/standard/tests/array/array_first_last_errors.phpt @@ -0,0 +1,20 @@ +--TEST-- +array_first()/array_last() error cases +--FILE-- + +--EXPECT-- +NULL +NULL +NULL +NULL From 71ffa9596a9c7b5c58f6da625fb3fe44cfce2778 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 7 May 2025 14:24:07 +0200 Subject: [PATCH 478/503] bump zip extension version to 1.22.6 --- ext/zip/php_zip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 1a1ffb1da3b8a..99409d3fc89d4 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -39,7 +39,7 @@ extern zend_module_entry zip_module_entry; /* Additionnal flags not from libzip */ #define ZIP_FL_OPEN_FILE_NOW (1u<<30) -#define PHP_ZIP_VERSION "1.22.5" +#define PHP_ZIP_VERSION "1.22.6" #ifdef HAVE_LIBZIP_VERSION #define LIBZIP_VERSION_STR zip_libzip_version() From c6a9beebffe8af58eeb0fb42af7f56455ae02ac3 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Thu, 8 May 2025 13:00:50 +0200 Subject: [PATCH 479/503] ext/standard/md5: Minor refactorings (#18518) - Use size_t type instead of int type - Use false instead of 0 - Remove wrapping comments --- ext/standard/md5.c | 19 +++++++------------ ext/standard/md5.h | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/ext/standard/md5.c b/ext/standard/md5.c index 899ff6aaeecb0..9d0f5f886a6bb 100644 --- a/ext/standard/md5.c +++ b/ext/standard/md5.c @@ -19,32 +19,29 @@ #include "php.h" #include "md5.h" -PHPAPI void make_digest(char *md5str, const unsigned char *digest) /* {{{ */ +PHPAPI void make_digest(char *md5str, const unsigned char *digest) { make_digest_ex(md5str, digest, 16); } -/* }}} */ -PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len) /* {{{ */ +PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, size_t len) { static const char hexits[17] = "0123456789abcdef"; - int i; - for (i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { md5str[i * 2] = hexits[digest[i] >> 4]; md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F]; } md5str[len * 2] = '\0'; } -/* }}} */ -/* {{{ Calculate the md5 hash of a string */ +/* Calculate the md5 hash of a string */ PHP_FUNCTION(md5) { zend_string *arg; - bool raw_output = 0; PHP_MD5_CTX context; unsigned char digest[16]; + bool raw_output = false; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_STR(arg) @@ -63,14 +60,13 @@ PHP_FUNCTION(md5) } } -/* }}} */ -/* {{{ Calculate the md5 hash of given filename */ +/* Calculate the md5 hash of given filename */ PHP_FUNCTION(md5_file) { char *arg; size_t arg_len; - bool raw_output = 0; + bool raw_output = false; unsigned char buf[1024]; unsigned char digest[16]; PHP_MD5_CTX context; @@ -113,7 +109,6 @@ PHP_FUNCTION(md5_file) make_digest_ex(Z_STRVAL_P(return_value), digest, 16); } } -/* }}} */ /* * This is an OpenSSL-compatible implementation of the RSA Data Security, diff --git a/ext/standard/md5.h b/ext/standard/md5.h index c488b5c534e36..5444abf46aec6 100644 --- a/ext/standard/md5.h +++ b/ext/standard/md5.h @@ -19,7 +19,7 @@ #define MD5_H PHPAPI void make_digest(char *md5str, const unsigned char *digest); -PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len); +PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, size_t len); /* * This is an OpenSSL-compatible implementation of the RSA Data Security, From 4527bafad07d3e365887fcf3d99c55b40bb2df59 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 21:08:18 -0700 Subject: [PATCH 480/503] gen_stub: break up closing tag in DOMCdataSection Otherwise GitHub's syntax highlighting treats it as the end of the code and stops highlighting --- build/gen_stub.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 1919d2e702a27..d15313d5c097d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1975,12 +1975,16 @@ private function getExampleSection(DOMDocument $doc, string $id): DOMElement { $prog = $doc->createElement('programlisting'); $prog->setAttribute('role', 'php'); + // So that GitHub syntax highlighting doesn't treat the closing tag + // in the DOMCdataSection as indication that it should stop syntax + // highlighting, break it up + $empty = ''; $code = new DOMCdataSection( << +?$empty> CODE_EXAMPLE ); From bfa2b92ca626fea32fa3a1c720617af739e0b117 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 21:14:22 -0700 Subject: [PATCH 481/503] gen_stub: add `ExposedDocComment::getInitCode()` Deduplicates the setting up of the `zend_string_init_interned()` call, removes the need for `ExposedDocComment::getLength()` and so that method is removed. --- build/gen_stub.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index d15313d5c097d..dd29d6ff539f8 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2728,9 +2728,8 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst if ($this->exposedDocComment) { $commentCode = "const_{$constName}_comment"; - $escapedComment = $this->exposedDocComment->escape(); - $escapedCommentLength = $this->exposedDocComment->getLength(); - $code .= "\tzend_string *$commentCode = zend_string_init_interned(\"$escapedComment\", $escapedCommentLength, 1);\n"; + $escapedCommentInit = $this->exposedDocComment->getInitCode(); + $code .= "\tzend_string *$commentCode = $escapedCommentInit\n"; } else { $commentCode = "NULL"; } @@ -3056,9 +3055,8 @@ public function getDeclaration(array $allConstInfos): string { if ($this->exposedDocComment) { $commentCode = "property_{$propertyName}_comment"; - $escapedComment = $this->exposedDocComment->escape(); - $escapedCommentLength = $this->exposedDocComment->getLength(); - $code .= "\tzend_string *$commentCode = zend_string_init_interned(\"$escapedComment\", $escapedCommentLength, 1);\n"; + $escapedCommentInit = $this->exposedDocComment->getInitCode(); + $code .= "\tzend_string *$commentCode = $escapedCommentInit\n"; } else { $commentCode = "NULL"; } @@ -3450,7 +3448,7 @@ public function getRegistration(array $allConstInfos): string $code .= "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n"; } - $code .= "\tclass_entry->doc_comment = zend_string_init_interned(\"" . $this->exposedDocComment->escape() . "\", " . $this->exposedDocComment->getLength() . ", 1);\n"; + $code .= "\tclass_entry->doc_comment = " . $this->exposedDocComment->getInitCode() . "\n"; if (!$php84MinimumCompatibility) { $code .= "#endif\n"; @@ -4278,8 +4276,8 @@ public function escape(): string { return str_replace("\n", '\n', addslashes($this->docComment)); } - public function getLength(): int { - return strlen($this->docComment); + public function getInitCode(): string { + return "zend_string_init_interned(\"" . $this->escape() . "\", " . strlen($this->docComment) . ", 1);"; } /** @param array $comments */ From 45d313bbd761a80ae745f483e3f2b2c2c4b4678f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 21:33:41 -0700 Subject: [PATCH 482/503] gen_stub: simplify `generateVersionDependentFlagCode()` * Return a string rather than an array, all callers just immediately used `implode()` to join the elements in the array with nothing between them * In the callers, inline some single-use variables with the template for the version-dependent code * Remove the callback to `array_filter` specifying that only items that are not `empty()` be removed - this is the default behavior --- build/gen_stub.php | 51 ++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index dd29d6ff539f8..9d21269af5e3a 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1396,7 +1396,7 @@ public function getFunctionEntry(): string { $flagsByPhpVersions, $this->minimumPhpVersionIdCompatibility ); - $functionEntryCode = rtrim(implode("", $flagsCode)); + $functionEntryCode = rtrim($flagsCode); } } } @@ -1439,25 +1439,21 @@ public function getFunctionEntry(): string { $docComment = $this->exposedDocComment ? '"' . $this->exposedDocComment->escape() . '"' : "NULL"; $framelessFuncInfosName = !empty($this->framelessFunctionInfos) ? $this->getFramelessFunctionInfosName() : "NULL"; - $template = "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s, $framelessFuncInfosName, $docComment)\n"; - $flagsCode = generateVersionDependentFlagCode( - $template, + $code .= generateVersionDependentFlagCode( + "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s, $framelessFuncInfosName, $docComment)\n", $php84AndAboveFlags, PHP_84_VERSION_ID ); - $code .= implode("", $flagsCode); if (!$php84MinimumCompatibility) { $code .= "#else\n"; $flags = array_slice($flagsByPhpVersions, 0, 4, true); - $template = "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s)\n"; - $flagsCode = generateVersionDependentFlagCode( - $template, + $code .= generateVersionDependentFlagCode( + "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s)\n", $flags, $this->minimumPhpVersionIdCompatibility ); - $code .= implode("", $flagsCode); $code .= "#endif\n"; } @@ -2750,12 +2746,11 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst } $template .= "zend_declare_typed_class_constant(class_entry, $nameCode, &const_{$constName}_value, %s, $commentCode, $typeCode);\n"; - $flagsCode = generateVersionDependentFlagCode( + $code .= generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); - $code .= implode("", $flagsCode); } if ($this->type && !$php83MinimumCompatibility) { @@ -2769,12 +2764,11 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst $template = "\t"; } $template .= "zend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, %s, $commentCode);\n"; - $flagsCode = generateVersionDependentFlagCode( + $code .= generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); - $code .= implode("", $flagsCode); } if ($this->type && !$php83MinimumCompatibility) { @@ -3074,12 +3068,11 @@ public function getDeclaration(array $allConstInfos): string { $template .= "zend_declare_property_ex(class_entry, $nameCode, &$zvalName, %s, $commentCode);\n"; } - $flagsCode = generateVersionDependentFlagCode( + $code .= generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); - $code .= implode("", $flagsCode); $code .= $stringRelease; @@ -3396,8 +3389,7 @@ public function getRegistration(array $allConstInfos): string $code .= "{\n"; - $flagCodes = generateVersionDependentFlagCode("%s", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); - $flags = implode("", $flagCodes); + $flags = generateVersionDependentFlagCode("%s", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); $classMethods = ($this->funcInfos === []) ? 'NULL' : "class_{$escapedName}_methods"; if ($this->type === "enum") { @@ -5403,9 +5395,9 @@ function generateOptimizerInfo(array $funcMap): string { /** * @param array $flagsByPhpVersions - * @return string[] + * @return string */ -function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPhpVersions, ?int $phpVersionIdMinimumCompatibility): array +function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPhpVersions, ?int $phpVersionIdMinimumCompatibility): string { $phpVersions = ALL_PHP_VERSION_IDS; sort($phpVersions); @@ -5414,10 +5406,10 @@ function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPh // No version compatibility is needed if ($phpVersionIdMinimumCompatibility === null) { if (empty($flagsByPhpVersions[$currentPhpVersion])) { - return []; + return ''; } - return [sprintf($codeTemplate, implode("|", $flagsByPhpVersions[$currentPhpVersion]))]; + return sprintf($codeTemplate, implode("|", $flagsByPhpVersions[$currentPhpVersion])); } // Remove flags which depend on a PHP version below the minimally supported one @@ -5429,15 +5421,11 @@ function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPh $flagsByPhpVersions = array_slice($flagsByPhpVersions, $index, null, true); // Remove empty version-specific flags - $flagsByPhpVersions = array_filter( - $flagsByPhpVersions, - static function (array $value): bool { - return !empty($value); - }); + $flagsByPhpVersions = array_filter($flagsByPhpVersions); // There are no version-specific flags if (empty($flagsByPhpVersions)) { - return []; + return ''; } // Remove version-specific flags which don't differ from the previous one @@ -5457,16 +5445,14 @@ static function (array $value): bool { reset($flagsByPhpVersions); $firstVersion = key($flagsByPhpVersions); if ($firstVersion === $phpVersionIdMinimumCompatibility) { - return [sprintf($codeTemplate, implode("|", reset($flagsByPhpVersions)))]; + return sprintf($codeTemplate, implode("|", reset($flagsByPhpVersions))); } } // Add the necessary conditions around the code using the version-specific flags - $result = []; + $code = ''; $i = 0; foreach (array_reverse($flagsByPhpVersions, true) as $version => $versionFlags) { - $code = ""; - $if = $i === 0 ? "#if" : "#elif"; $endif = $i === $flagCount - 1 ? "#endif\n" : ""; @@ -5475,11 +5461,10 @@ static function (array $value): bool { $code .= sprintf($codeTemplate, implode("|", $versionFlags)); $code .= $endif; - $result[] = $code; $i++; } - return $result; + return $code; } /** From 0d79039027b648c91212baee5a715d014a36509e Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 21:39:00 -0700 Subject: [PATCH 483/503] gen_stub: simplify `ArgInfo::getDefaultValueAsMethodSynopsisString()` There is no need to add special handling for the default value of `null`, since it is not loosely-equals to any of the strings 'UNKNOWN', 'false', 'true', or 'null' it will just be returned directly anyway. --- build/gen_stub.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 9d21269af5e3a..4643a424f9356 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -848,10 +848,6 @@ public function getDefaultValueAsArginfoString(): string { } public function getDefaultValueAsMethodSynopsisString(): ?string { - if ($this->defaultValue === null) { - return null; - } - switch ($this->defaultValue) { case 'UNKNOWN': return null; From 24b7c7a36533db0319c9de3b2c03f4f806fdc6cd Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 21:55:03 -0700 Subject: [PATCH 484/503] gen_stub: add `ArgInfo::toZendInfo()` Move the logic out of `funcInfoToCode()` and update it. In the process, make `ArgInfo::getDefaultValueAsArginfoString()` private. --- build/gen_stub.php | 92 +++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 4643a424f9356..81fd0ccece072 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -839,7 +839,7 @@ public function hasProperDefaultValue(): bool { return $this->defaultValue !== null && $this->defaultValue !== "UNKNOWN"; } - public function getDefaultValueAsArginfoString(): string { + private function getDefaultValueAsArginfoString(): string { if ($this->hasProperDefaultValue()) { return '"' . addslashes($this->defaultValue) . '"'; } @@ -859,6 +859,50 @@ public function getDefaultValueAsMethodSynopsisString(): ?string { return $this->defaultValue; } + + public function toZendInfo(): string { + $argKind = $this->isVariadic ? "ARG_VARIADIC" : "ARG"; + $argDefaultKind = $this->hasProperDefaultValue() ? "_WITH_DEFAULT_VALUE" : ""; + $argType = $this->type; + if ($argType !== null) { + if (null !== $simpleArgType = $argType->tryToSimpleType()) { + if ($simpleArgType->isBuiltin) { + return sprintf( + "\tZEND_%s_TYPE_INFO%s(%s, %s, %s, %d%s)\n", + $argKind, $argDefaultKind, $this->sendBy, $this->name, + $simpleArgType->toTypeCode(), $argType->isNullable(), + $this->hasProperDefaultValue() ? ", " . $this->getDefaultValueAsArginfoString() : "" + ); + } + return sprintf( + "\tZEND_%s_OBJ_INFO%s(%s, %s, %s, %d%s)\n", + $argKind, $argDefaultKind, $this->sendBy, $this->name, + $simpleArgType->toEscapedName(), $argType->isNullable(), + $this->hasProperDefaultValue() ? ", " . $this->getDefaultValueAsArginfoString() : "" + ); + } + $arginfoType = $argType->toArginfoType(); + if ($arginfoType->hasClassType()) { + return sprintf( + "\tZEND_%s_OBJ_TYPE_MASK(%s, %s, %s, %s%s)\n", + $argKind, $this->sendBy, $this->name, + $arginfoType->toClassTypeString(), $arginfoType->toTypeMask(), + !$this->isVariadic ? ", " . $this->getDefaultValueAsArginfoString() : "" + ); + } + return sprintf( + "\tZEND_%s_TYPE_MASK(%s, %s, %s, %s)\n", + $argKind, $this->sendBy, $this->name, + $arginfoType->toTypeMask(), + $this->getDefaultValueAsArginfoString() + ); + } + return sprintf( + "\tZEND_%s_INFO%s(%s, %s%s)\n", + $argKind, $argDefaultKind, $this->sendBy, $this->name, + $this->hasProperDefaultValue() ? ", " . $this->getDefaultValueAsArginfoString() : "" + ); + } } interface VariableLikeName { @@ -5029,51 +5073,7 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { } foreach ($funcInfo->args as $argInfo) { - $argKind = $argInfo->isVariadic ? "ARG_VARIADIC" : "ARG"; - $argDefaultKind = $argInfo->hasProperDefaultValue() ? "_WITH_DEFAULT_VALUE" : ""; - $argType = $argInfo->type; - if ($argType !== null) { - if (null !== $simpleArgType = $argType->tryToSimpleType()) { - if ($simpleArgType->isBuiltin) { - $code .= sprintf( - "\tZEND_%s_TYPE_INFO%s(%s, %s, %s, %d%s)\n", - $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, - $simpleArgType->toTypeCode(), $argType->isNullable(), - $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" - ); - } else { - $code .= sprintf( - "\tZEND_%s_OBJ_INFO%s(%s, %s, %s, %d%s)\n", - $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, - $simpleArgType->toEscapedName(), $argType->isNullable(), - $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" - ); - } - } else { - $arginfoType = $argType->toArginfoType(); - if ($arginfoType->hasClassType()) { - $code .= sprintf( - "\tZEND_%s_OBJ_TYPE_MASK(%s, %s, %s, %s%s)\n", - $argKind, $argInfo->sendBy, $argInfo->name, - $arginfoType->toClassTypeString(), $arginfoType->toTypeMask(), - !$argInfo->isVariadic ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" - ); - } else { - $code .= sprintf( - "\tZEND_%s_TYPE_MASK(%s, %s, %s, %s)\n", - $argKind, $argInfo->sendBy, $argInfo->name, - $arginfoType->toTypeMask(), - $argInfo->getDefaultValueAsArginfoString() - ); - } - } - } else { - $code .= sprintf( - "\tZEND_%s_INFO%s(%s, %s%s)\n", - $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, - $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" - ); - } + $code .= $argInfo->toZendInfo(); } $code .= "ZEND_END_ARG_INFO()"; From b5361d75e0997035ded5fe2a89c3ece447ce52bd Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 22:44:45 -0700 Subject: [PATCH 485/503] gen_stub: add `ReturnInfo::beginArgInfo()` The vast majority of the decisions about the use of `ZEND_BEGIN_ARG_INFO_EX` or one of its variations are based on the return information of the function - is the type builtin, is the return information tentative, does it include an object mask, etc. Accordingly, move the logic into the `ReturnInfo` class. The logic is actually moved into two methods, `ReturnInfo::beginArgInfo()`, which needs to handle the case of tentative returns being used when PHP < 8.1 is supported, and `::beginArgInfoCompatible()`, which can assume that PHP 8.1+ is supported and thus make use of early returns and guard clauses. Further improvements to the logic will be made in a subsequent commit. In the process, make `ReturnInfo::$byRef` private. --- build/gen_stub.php | 129 ++++++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 60 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 81fd0ccece072..c8a2e7a3fb48d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1146,7 +1146,7 @@ class ReturnInfo { self::REFCOUNT_N, ]; - public /* readonly */ bool $byRef; + private /* readonly */ bool $byRef; // NOT readonly - gets removed when discarding info for older PHP versions public ?Type $type; public /* readonly */ ?Type $phpDocType; @@ -1193,6 +1193,69 @@ private function setRefcount(?string $refcount): void $this->refcount = $refcount; } + + public function beginArgInfo(string $funcInfoName, int $minArgs, bool $php81MinimumCompatibility): string { + $code = $this->beginArgInfoCompatible($funcInfoName, $minArgs); + if ($this->type !== null && $this->tentativeReturnType && !$php81MinimumCompatibility) { + $realCode = "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ")\n"; + $realCode .= $code; + $realCode .= sprintf( + "#else\nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n#endif\n", + $funcInfoName, $this->byRef, $minArgs + ); + return $realCode; + } + return $code; + } + + /** + * Assumes PHP 8.1 compatibility, if that is not the case the caller is + * responsible for making the use of a tentative return type conditional + * based on the PHP version. Separate to allow using early returns + */ + private function beginArgInfoCompatible(string $funcInfoName, int $minArgs): string { + if ($this->type !== null) { + if (null !== $simpleReturnType = $this->type->tryToSimpleType()) { + if ($simpleReturnType->isBuiltin) { + return sprintf( + "%s(%s, %d, %d, %s, %d)\n", + $this->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX", + $funcInfoName, $this->byRef, + $minArgs, + $simpleReturnType->toTypeCode(), $this->type->isNullable() + ); + } + return sprintf( + "%s(%s, %d, %d, %s, %d)\n", + $this->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX", + $funcInfoName, $this->byRef, + $minArgs, + $simpleReturnType->toEscapedName(), $this->type->isNullable() + ); + } + $arginfoType = $this->type->toArginfoType(); + if ($arginfoType->hasClassType()) { + return sprintf( + "%s(%s, %d, %d, %s, %s)\n", + $this->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX", + $funcInfoName, $this->byRef, + $minArgs, + $arginfoType->toClassTypeString(), $arginfoType->toTypeMask() + ); + } + return sprintf( + "%s(%s, %d, %d, %s)\n", + $this->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX", + $funcInfoName, $this->byRef, + $minArgs, + $arginfoType->toTypeMask() + ); + } + return sprintf( + "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n", + $funcInfoName, $this->byRef, $minArgs + ); + } } class FuncInfo { @@ -5012,65 +5075,11 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { } function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { - $code = ''; - $returnType = $funcInfo->return->type; - $isTentativeReturnType = $funcInfo->return->tentativeReturnType; - $php81MinimumCompatibility = $fileInfo->getMinimumPhpVersionIdCompatibility() === null || $fileInfo->getMinimumPhpVersionIdCompatibility() >= PHP_81_VERSION_ID; - - if ($returnType !== null) { - if ($isTentativeReturnType && !$php81MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ")\n"; - } - if (null !== $simpleReturnType = $returnType->tryToSimpleType()) { - if ($simpleReturnType->isBuiltin) { - $code .= sprintf( - "%s(%s, %d, %d, %s, %d)\n", - $isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, - $funcInfo->numRequiredArgs, - $simpleReturnType->toTypeCode(), $returnType->isNullable() - ); - } else { - $code .= sprintf( - "%s(%s, %d, %d, %s, %d)\n", - $isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, - $funcInfo->numRequiredArgs, - $simpleReturnType->toEscapedName(), $returnType->isNullable() - ); - } - } else { - $arginfoType = $returnType->toArginfoType(); - if ($arginfoType->hasClassType()) { - $code .= sprintf( - "%s(%s, %d, %d, %s, %s)\n", - $isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, - $funcInfo->numRequiredArgs, - $arginfoType->toClassTypeString(), $arginfoType->toTypeMask() - ); - } else { - $code .= sprintf( - "%s(%s, %d, %d, %s)\n", - $isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, - $funcInfo->numRequiredArgs, - $arginfoType->toTypeMask() - ); - } - } - if ($isTentativeReturnType && !$php81MinimumCompatibility) { - $code .= sprintf( - "#else\nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n#endif\n", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, $funcInfo->numRequiredArgs - ); - } - } else { - $code .= sprintf( - "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n", - $funcInfo->getArgInfoName(), $funcInfo->return->byRef, $funcInfo->numRequiredArgs - ); - } + $code = $funcInfo->return->beginArgInfo( + $funcInfo->getArgInfoName(), + $funcInfo->numRequiredArgs, + $fileInfo->getMinimumPhpVersionIdCompatibility() === null || $fileInfo->getMinimumPhpVersionIdCompatibility() >= PHP_81_VERSION_ID + ); foreach ($funcInfo->args as $argInfo) { $code .= $argInfo->toZendInfo(); From 39a6d6086e0f39aef9efadf6f40e8b33df70b0bd Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 22:51:16 -0700 Subject: [PATCH 486/503] gen_stub: move `funcInfoToCode()` into `FuncInfo` Reduce the number of global functions by moving it to instance method `FuncInfo::toArgInfoCode()`. In the process, make `FuncInfo::$numRequiredArgs` private. --- build/gen_stub.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index c8a2e7a3fb48d..2c08c564c3523 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1270,7 +1270,7 @@ class FuncInfo { /** @var ArgInfo[] */ public /* readonly */ array $args; public /* readonly */ ReturnInfo $return; - public /* readonly */ int $numRequiredArgs; + private /* readonly */ int $numRequiredArgs; public /* readonly */ ?string $cond; public bool $isUndocumentable; private ?int $minimumPhpVersionIdCompatibility; @@ -2228,6 +2228,21 @@ public function findEquivalent(array $generatedFuncInfos): ?FuncInfo { return null; } + public function toArgInfoCode(?int $minPHPCompatability): string { + $code = $this->return->beginArgInfo( + $this->getArgInfoName(), + $this->numRequiredArgs, + $minPHPCompatability === null || $minPHPCompatability >= PHP_81_VERSION_ID + ); + + foreach ($this->args as $argInfo) { + $code .= $argInfo->toZendInfo(); + } + + $code .= "ZEND_END_ARG_INFO()"; + return $code . "\n"; + } + public function __clone() { foreach ($this->args as $key => $argInfo) { @@ -5074,21 +5089,6 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { return $fileInfo; } -function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { - $code = $funcInfo->return->beginArgInfo( - $funcInfo->getArgInfoName(), - $funcInfo->numRequiredArgs, - $fileInfo->getMinimumPhpVersionIdCompatibility() === null || $fileInfo->getMinimumPhpVersionIdCompatibility() >= PHP_81_VERSION_ID - ); - - foreach ($funcInfo->args as $argInfo) { - $code .= $argInfo->toZendInfo(); - } - - $code .= "ZEND_END_ARG_INFO()"; - return $code . "\n"; -} - /** * @template T * @param iterable $infos @@ -5168,7 +5168,7 @@ static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { $funcInfo->getArgInfoName(), $generatedFuncInfo->getArgInfoName() ); } else { - $code = funcInfoToCode($fileInfo, $funcInfo); + $code = $funcInfo->toArgInfoCode($fileInfo->getMinimumPhpVersionIdCompatibility()); } $generatedFuncInfos[] = $funcInfo; From 48613915015b89f5be9df09bc12eb1c35a9f8d60 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 16 Mar 2025 23:35:20 -0700 Subject: [PATCH 487/503] gen_stub: inline some single-use variables --- build/gen_stub.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 2c08c564c3523..adcdfd5b2607d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -710,9 +710,7 @@ public function getTypeForDoc(DOMDocument $doc): DOMElement { } } else { $type = $this->types[0]; - $name = $type->name; - - $typeElement = $doc->createElement('type', $name); + $typeElement = $doc->createElement('type', $type->name); } return $typeElement; @@ -1937,9 +1935,8 @@ private function getReturnValueSection(DOMDocument $doc): DOMElement { $returnDescriptionPara->appendChild(new DOMText("Description.")); } else if (count($returnType->types) === 1) { $type = $returnType->types[0]; - $name = $type->name; - switch ($name) { + switch ($type->name) { case 'void': $descriptionNode = $doc->createEntityReference('return.void'); break; From 722eba20aefa23c2db0ed707e7cc2ae4acdf6eea Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 17 Mar 2025 00:27:58 -0700 Subject: [PATCH 488/503] gen_stub: drop unused parameters The following parameters were either unused before this commit or became unused as part of updating callers to stop passing unused parameters to other functions updated in this commit: * `FuncInfo::getMethodSynopsisDocument()` - `$funcMap`, `$aliasMap` * `FuncInfo::getMethodSynopsisElement()` - `$funcMap`, `$aliasMap` * `ConstInfo::getGlobalConstDeclaration()` - `$allConstInfos` * `generateMethodSynopses()` - `$aliasMap` * `replaceMethodSynopses()` - `$aliasMap` --- build/gen_stub.php | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index adcdfd5b2607d..dfbd2d6a92f63 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1684,11 +1684,9 @@ private function generateRefSect1(DOMDocument $doc, string $role): DOMElement { } /** - * @param array $funcMap - * @param array $aliasMap * @throws Exception */ - public function getMethodSynopsisDocument(array $funcMap, array $aliasMap): ?string { + public function getMethodSynopsisDocument(): ?string { $REFSEC1_SEPERATOR = "\n\n "; $doc = new DOMDocument("1.0", "utf-8"); @@ -1733,7 +1731,7 @@ public function getMethodSynopsisDocument(array $funcMap, array $aliasMap): ?str /* Creation of */ $descriptionRefSec = $this->generateRefSect1($doc, 'description'); - $methodSynopsis = $this->getMethodSynopsisElement($funcMap, $aliasMap, $doc); + $methodSynopsis = $this->getMethodSynopsisElement($doc); if (!$methodSynopsis) { return null; } @@ -2117,11 +2115,9 @@ private function getExampleSection(DOMDocument $doc, string $id): DOMElement { } /** - * @param array $funcMap - * @param array $aliasMap * @throws Exception */ - public function getMethodSynopsisElement(array $funcMap, array $aliasMap, DOMDocument $doc): ?DOMElement { + public function getMethodSynopsisElement(DOMDocument $doc): ?DOMElement { if ($this->hasParamWithUnknownDefaultValue()) { return null; } @@ -2773,7 +2769,7 @@ public function getDeclaration(array $allConstInfos): string if ($this->name->isClassConst()) { $code .= $this->getClassConstDeclaration($value, $allConstInfos); } else { - $code .= $this->getGlobalConstDeclaration($value, $allConstInfos); + $code .= $this->getGlobalConstDeclaration($value); } $code .= $this->getValueAssertion($value); @@ -2784,8 +2780,7 @@ public function getDeclaration(array $allConstInfos): string return $code; } - /** @param array $allConstInfos */ - private function getGlobalConstDeclaration(EvaluatedValue $value, array $allConstInfos): string + private function getGlobalConstDeclaration(EvaluatedValue $value): string { $constName = str_replace('\\', '\\\\', $this->name->__toString()); $constValue = $value->value; @@ -5783,14 +5778,13 @@ function getReplacedSynopsisXml(string $xml): string /** * @param array $funcMap - * @param array $aliasMap * @return array */ -function generateMethodSynopses(array $funcMap, array $aliasMap): array { +function generateMethodSynopses(array $funcMap): array { $result = []; foreach ($funcMap as $funcInfo) { - $methodSynopsis = $funcInfo->getMethodSynopsisDocument($funcMap, $aliasMap); + $methodSynopsis = $funcInfo->getMethodSynopsisDocument(); if ($methodSynopsis !== null) { $result[$funcInfo->name->getMethodSynopsisFilename() . ".xml"] = $methodSynopsis; } @@ -5801,7 +5795,6 @@ function generateMethodSynopses(array $funcMap, array $aliasMap): array { /** * @param array $funcMap - * @param array $aliasMap * @param array $methodSynopsisWarnings * @param array $undocumentedFuncMap * @return array @@ -5809,7 +5802,6 @@ function generateMethodSynopses(array $funcMap, array $aliasMap): array { function replaceMethodSynopses( string $targetDirectory, array $funcMap, - array $aliasMap, bool $isVerifyManual, array &$methodSynopsisWarnings, array &$undocumentedFuncMap @@ -5908,7 +5900,7 @@ function replaceMethodSynopses( $funcInfo = $funcMap[$funcName]; $documentedFuncMap[$funcInfo->name->__toString()] = $funcInfo->name->__toString(); - $newMethodSynopsis = $funcInfo->getMethodSynopsisElement($funcMap, $aliasMap, $doc); + $newMethodSynopsis = $funcInfo->getMethodSynopsisElement($doc); if ($newMethodSynopsis === null) { continue; } @@ -6326,7 +6318,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } if ($generateMethodSynopses) { - $methodSynopses = generateMethodSynopses($funcMap, $aliasMap); + $methodSynopses = generateMethodSynopses($funcMap); if (!file_exists($manualTarget)) { mkdir($manualTarget); } @@ -6345,7 +6337,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } if ($replaceMethodSynopses || $verifyManual) { - $methodSynopses = replaceMethodSynopses($manualTarget, $funcMap, $aliasMap, $verifyManual, $methodSynopsisWarnings, $undocumentedFuncMap); + $methodSynopses = replaceMethodSynopses($manualTarget, $funcMap, $verifyManual, $methodSynopsisWarnings, $undocumentedFuncMap); if ($replaceMethodSynopses) { foreach ($methodSynopses as $filename => $content) { From ec3ecdc2c810b71ecc4d1f1627a81f5def3e6d6a Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 12:10:28 -0700 Subject: [PATCH 489/503] gen_stub: documentation updates * Use `@param` instead of `@var` for parameters * Fix type of `$attributeGroups` in `AttributeInfo::createFromGroups()` * Remove extra documentation of `$allConstInfo` for `ClassInfo::getClassSynopsisDocument()`, it is already documented under the correct name `$allConstInfos` * Remove unneeded `@throws` --- build/gen_stub.php | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index dfbd2d6a92f63..9d4a9138d0502 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1683,9 +1683,6 @@ private function generateRefSect1(DOMDocument $doc, string $role): DOMElement { return $refSec; } - /** - * @throws Exception - */ public function getMethodSynopsisDocument(): ?string { $REFSEC1_SEPERATOR = "\n\n "; @@ -2114,9 +2111,6 @@ private function getExampleSection(DOMDocument $doc, string $id): DOMElement { return $refSec; } - /** - * @throws Exception - */ public function getMethodSynopsisElement(DOMDocument $doc): ?DOMElement { if ($this->hasParamWithUnknownDefaultValue()) { return null; @@ -2438,7 +2432,7 @@ abstract class VariableLike protected /* readonly */ ?ExposedDocComment $exposedDocComment; /** - * @var AttributeInfo[] $attributes + * @param AttributeInfo[] $attributes */ public function __construct( int $flags, @@ -2621,7 +2615,7 @@ class ConstInfo extends VariableLike private /* readonly */ bool $isFileCacheAllowed; /** - * @var AttributeInfo[] $attributes + * @param AttributeInfo[] $attributes */ public function __construct( AbstractConstName $name, @@ -3075,7 +3069,7 @@ class PropertyInfo extends VariableLike ]; /** - * @var AttributeInfo[] $attributes + * @param AttributeInfo[] $attributes */ public function __construct( PropertyName $name, @@ -3373,7 +3367,7 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC } /** - * @param array> $attributeGroups + * @param AttributeGroup[] $attributeGroups * @return AttributeInfo[] */ public static function createFromGroups(array $attributeGroups): array { @@ -3733,7 +3727,6 @@ public function discardInfoForOldPhpVersions(?int $phpVersionIdMinimumCompatibil /** * @param array $classMap * @param array $allConstInfos - * @param iterable $allConstInfo */ public function getClassSynopsisDocument(array $classMap, array $allConstInfos): ?string { $doc = new DOMDocument(); From 1c9b6b84df98cbea4d80f508dfa2d54a0ce0e7e2 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 12:56:29 -0700 Subject: [PATCH 490/503] gen_stub: move `handleStatements()` into `FileInfo` Reduce the number of global functions by moving it to instance method `FileInfo::handleStatements()`. --- build/gen_stub.php | 290 ++++++++++++++++++++++----------------------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 9d4a9138d0502..b31af1d58c908 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4298,6 +4298,150 @@ public function getMinimumPhpVersionIdCompatibility(): ?int { public function shouldGenerateLegacyArginfo(): bool { return $this->minimumPhpVersionIdCompatibility !== null && $this->minimumPhpVersionIdCompatibility < PHP_80_VERSION_ID; } + + public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { + $conds = []; + foreach ($stmts as $stmt) { + $cond = handlePreprocessorConditions($conds, $stmt); + + if ($stmt instanceof Stmt\Nop) { + continue; + } + + if ($stmt instanceof Stmt\Namespace_) { + $this->handleStatements($stmt->stmts, $prettyPrinter); + continue; + } + + if ($stmt instanceof Stmt\Const_) { + foreach ($stmt->consts as $const) { + $this->constInfos[] = parseConstLike( + $prettyPrinter, + new ConstName($const->namespacedName, $const->name->toString()), + $const, + 0, + null, + $stmt->getComments(), + $cond, + $this->isUndocumentable, + $this->getMinimumPhpVersionIdCompatibility(), + [] + ); + } + continue; + } + + if ($stmt instanceof Stmt\Function_) { + $this->funcInfos[] = parseFunctionLike( + $prettyPrinter, + new FunctionName($stmt->namespacedName), + 0, + 0, + $stmt, + $cond, + $this->isUndocumentable, + $this->getMinimumPhpVersionIdCompatibility() + ); + continue; + } + + if ($stmt instanceof Stmt\ClassLike) { + $className = $stmt->namespacedName; + $constInfos = []; + $propertyInfos = []; + $methodInfos = []; + $enumCaseInfos = []; + foreach ($stmt->stmts as $classStmt) { + $cond = handlePreprocessorConditions($conds, $classStmt); + if ($classStmt instanceof Stmt\Nop) { + continue; + } + + $classFlags = $stmt instanceof Class_ ? $stmt->flags : 0; + $abstractFlag = $stmt instanceof Stmt\Interface_ ? Modifiers::ABSTRACT : 0; + + if ($classStmt instanceof Stmt\ClassConst) { + foreach ($classStmt->consts as $const) { + $constInfos[] = parseConstLike( + $prettyPrinter, + new ClassConstName($className, $const->name->toString()), + $const, + $classStmt->flags, + $classStmt->type, + $classStmt->getComments(), + $cond, + $this->isUndocumentable, + $this->getMinimumPhpVersionIdCompatibility(), + AttributeInfo::createFromGroups($classStmt->attrGroups) + ); + } + } else if ($classStmt instanceof Stmt\Property) { + if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { + throw new Exception("Visibility modifier is required"); + } + foreach ($classStmt->props as $property) { + $propertyInfos[] = parseProperty( + $className, + $classFlags, + $classStmt->flags, + $property, + $classStmt->type, + $classStmt->getComments(), + $prettyPrinter, + $this->getMinimumPhpVersionIdCompatibility(), + AttributeInfo::createFromGroups($classStmt->attrGroups) + ); + } + } else if ($classStmt instanceof Stmt\ClassMethod) { + if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { + throw new Exception("Visibility modifier is required"); + } + $methodInfos[] = parseFunctionLike( + $prettyPrinter, + new MethodName($className, $classStmt->name->toString()), + $classFlags, + $classStmt->flags | $abstractFlag, + $classStmt, + $cond, + $this->isUndocumentable, + $this->getMinimumPhpVersionIdCompatibility() + ); + } else if ($classStmt instanceof Stmt\EnumCase) { + $enumCaseInfos[] = new EnumCaseInfo( + $classStmt->name->toString(), $classStmt->expr); + } else { + throw new Exception("Not implemented {$classStmt->getType()}"); + } + } + + $this->classInfos[] = parseClass( + $className, + $stmt, + $constInfos, + $propertyInfos, + $methodInfos, + $enumCaseInfos, + $cond, + $this->getMinimumPhpVersionIdCompatibility(), + $this->isUndocumentable + ); + continue; + } + + if ($stmt instanceof Stmt\Expression) { + $expr = $stmt->expr; + if ($expr instanceof Expr\Include_) { + $this->dependencies[] = (string)EvaluatedValue::createFromExpression($expr->expr, null, null, [])->value; + continue; + } + } + + throw new Exception("Unexpected node {$stmt->getType()}"); + } + if (!empty($conds)) { + throw new Exception("Unterminated preprocessor conditions"); + } + } } class DocCommentTag { @@ -4910,150 +5054,6 @@ function getFileDocComments(array $stmts): array { ); } -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; - } - - if ($stmt instanceof Stmt\Const_) { - foreach ($stmt->consts as $const) { - $fileInfo->constInfos[] = parseConstLike( - $prettyPrinter, - new ConstName($const->namespacedName, $const->name->toString()), - $const, - 0, - null, - $stmt->getComments(), - $cond, - $fileInfo->isUndocumentable, - $fileInfo->getMinimumPhpVersionIdCompatibility(), - [] - ); - } - continue; - } - - if ($stmt instanceof Stmt\Function_) { - $fileInfo->funcInfos[] = parseFunctionLike( - $prettyPrinter, - new FunctionName($stmt->namespacedName), - 0, - 0, - $stmt, - $cond, - $fileInfo->isUndocumentable, - $fileInfo->getMinimumPhpVersionIdCompatibility() - ); - continue; - } - - if ($stmt instanceof Stmt\ClassLike) { - $className = $stmt->namespacedName; - $constInfos = []; - $propertyInfos = []; - $methodInfos = []; - $enumCaseInfos = []; - foreach ($stmt->stmts as $classStmt) { - $cond = handlePreprocessorConditions($conds, $classStmt); - if ($classStmt instanceof Stmt\Nop) { - continue; - } - - $classFlags = $stmt instanceof Class_ ? $stmt->flags : 0; - $abstractFlag = $stmt instanceof Stmt\Interface_ ? Modifiers::ABSTRACT : 0; - - if ($classStmt instanceof Stmt\ClassConst) { - foreach ($classStmt->consts as $const) { - $constInfos[] = parseConstLike( - $prettyPrinter, - new ClassConstName($className, $const->name->toString()), - $const, - $classStmt->flags, - $classStmt->type, - $classStmt->getComments(), - $cond, - $fileInfo->isUndocumentable, - $fileInfo->getMinimumPhpVersionIdCompatibility(), - AttributeInfo::createFromGroups($classStmt->attrGroups) - ); - } - } else if ($classStmt instanceof Stmt\Property) { - if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { - throw new Exception("Visibility modifier is required"); - } - foreach ($classStmt->props as $property) { - $propertyInfos[] = parseProperty( - $className, - $classFlags, - $classStmt->flags, - $property, - $classStmt->type, - $classStmt->getComments(), - $prettyPrinter, - $fileInfo->getMinimumPhpVersionIdCompatibility(), - AttributeInfo::createFromGroups($classStmt->attrGroups) - ); - } - } else if ($classStmt instanceof Stmt\ClassMethod) { - if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { - throw new Exception("Visibility modifier is required"); - } - $methodInfos[] = parseFunctionLike( - $prettyPrinter, - new MethodName($className, $classStmt->name->toString()), - $classFlags, - $classStmt->flags | $abstractFlag, - $classStmt, - $cond, - $fileInfo->isUndocumentable, - $fileInfo->getMinimumPhpVersionIdCompatibility() - ); - } else if ($classStmt instanceof Stmt\EnumCase) { - $enumCaseInfos[] = new EnumCaseInfo( - $classStmt->name->toString(), $classStmt->expr); - } else { - throw new Exception("Not implemented {$classStmt->getType()}"); - } - } - - $fileInfo->classInfos[] = parseClass( - $className, - $stmt, - $constInfos, - $propertyInfos, - $methodInfos, - $enumCaseInfos, - $cond, - $fileInfo->getMinimumPhpVersionIdCompatibility(), - $fileInfo->isUndocumentable - ); - continue; - } - - if ($stmt instanceof Stmt\Expression) { - $expr = $stmt->expr; - if ($expr instanceof Expr\Include_) { - $fileInfo->dependencies[] = (string)EvaluatedValue::createFromExpression($expr->expr, null, null, [])->value; - continue; - } - } - - throw new Exception("Unexpected node {$stmt->getType()}"); - } - if (!empty($conds)) { - throw new Exception("Unterminated preprocessor conditions"); - } -} - function parseStubFile(string $code): FileInfo { $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative()); $nodeTraverser = new PhpParser\NodeTraverser; @@ -5070,7 +5070,7 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { $fileTags = parseDocComments(getFileDocComments($stmts)); $fileInfo = new FileInfo($fileTags); - handleStatements($fileInfo, $stmts, $prettyPrinter); + $fileInfo->handleStatements($stmts, $prettyPrinter); return $fileInfo; } From ce3990c1d3976951c1fe78ef6b7f33afbd63d83b Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 12:58:27 -0700 Subject: [PATCH 491/503] gen_stub: move `handlePreprocessorConditions()` into `FileInfo()` Reduce the number of global functions by moving it to static method `FileInfo::handlePreprocessorConditions()`. Since it is only used by `FileInfo::handleStatements()`, also make it private. --- build/gen_stub.php | 60 +++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index b31af1d58c908..d95c32a549c59 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4302,7 +4302,7 @@ public function shouldGenerateLegacyArginfo(): bool { public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { $conds = []; foreach ($stmts as $stmt) { - $cond = handlePreprocessorConditions($conds, $stmt); + $cond = self::handlePreprocessorConditions($conds, $stmt); if ($stmt instanceof Stmt\Nop) { continue; @@ -4352,7 +4352,7 @@ public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrin $methodInfos = []; $enumCaseInfos = []; foreach ($stmt->stmts as $classStmt) { - $cond = handlePreprocessorConditions($conds, $classStmt); + $cond = self::handlePreprocessorConditions($conds, $classStmt); if ($classStmt instanceof Stmt\Nop) { continue; } @@ -4442,6 +4442,34 @@ public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrin throw new Exception("Unterminated preprocessor conditions"); } } + + private static function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string { + foreach ($stmt->getComments() as $comment) { + $text = trim($comment->getText()); + if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) { + $conds[] = $matches[1]; + } else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) { + $conds[] = "defined($matches[1])"; + } else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) { + $conds[] = "!defined($matches[1])"; + } else if (preg_match('/^#\s*else$/', $text)) { + if (empty($conds)) { + throw new Exception("Encountered else without corresponding #if"); + } + $cond = array_pop($conds); + $conds[] = "!($cond)"; + } else if (preg_match('/^#\s*endif$/', $text)) { + if (empty($conds)) { + throw new Exception("Encountered #endif without corresponding #if"); + } + array_pop($conds); + } else if ($text[0] === '#') { + throw new Exception("Unrecognized preprocessor directive \"$text\""); + } + } + + return empty($conds) ? null : implode(' && ', $conds); + } } class DocCommentTag { @@ -5014,34 +5042,6 @@ function parseClass( ); } -function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string { - foreach ($stmt->getComments() as $comment) { - $text = trim($comment->getText()); - if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) { - $conds[] = $matches[1]; - } else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) { - $conds[] = "defined($matches[1])"; - } else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) { - $conds[] = "!defined($matches[1])"; - } else if (preg_match('/^#\s*else$/', $text)) { - if (empty($conds)) { - throw new Exception("Encountered else without corresponding #if"); - } - $cond = array_pop($conds); - $conds[] = "!($cond)"; - } else if (preg_match('/^#\s*endif$/', $text)) { - if (empty($conds)) { - throw new Exception("Encountered #endif without corresponding #if"); - } - array_pop($conds); - } else if ($text[0] === '#') { - throw new Exception("Unrecognized preprocessor directive \"$text\""); - } - } - - return empty($conds) ? null : implode(' && ', $conds); -} - /** @return DocComment[] */ function getFileDocComments(array $stmts): array { if (empty($stmts)) { From d42bac2866a2554cdc04b13ac91a0c89b80e53db Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 13:06:46 -0700 Subject: [PATCH 492/503] gen_stub: move `parseDocComments()` into `DocCommentTag` Reduce the number of global functions by moving it to static method `DocCommentTag::parseDocComments()`. --- build/gen_stub.php | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index d95c32a549c59..64c22f1873aac 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4528,6 +4528,25 @@ public function getVariableName(): string { return $matches["name"]; } + + /** @return DocCommentTag[] */ + public static function parseDocComments(array $comments): array { + $tags = []; + foreach ($comments as $comment) { + if (!($comment instanceof DocComment)) { + continue; + } + $commentText = substr($comment->getText(), 2, -2); + foreach (explode("\n", $commentText) as $commentLine) { + $regex = '/^\*\s*@([a-z-]+)(?:\s+(.+))?$/'; + if (preg_match($regex, trim($commentLine), $matches)) { + $tags[] = new DocCommentTag($matches[1], $matches[2] ?? null); + } + } + } + + return $tags; + } } // Instances of ExposedDocComment are immutable and do not need to be cloned @@ -4571,25 +4590,6 @@ public static function extractExposedComment(array $comments): ?ExposedDocCommen } } -/** @return DocCommentTag[] */ -function parseDocComments(array $comments): array { - $tags = []; - foreach ($comments as $comment) { - if (!($comment instanceof DocComment)) { - continue; - } - $commentText = substr($comment->getText(), 2, -2); - foreach (explode("\n", $commentText) as $commentLine) { - $regex = '/^\*\s*@([a-z-]+)(?:\s+(.+))?$/'; - if (preg_match($regex, trim($commentLine), $matches)) { - $tags[] = new DocCommentTag($matches[1], $matches[2] ?? null); - } - } - } - - return $tags; -} - // Instances of FramelessFunctionInfo are immutable and do not need to be cloned // when held by an object that is cloned class FramelessFunctionInfo { @@ -4628,7 +4628,7 @@ function parseFunctionLike( $framelessFunctionInfos = []; if ($comments) { - $tags = parseDocComments($comments); + $tags = DocCommentTag::parseDocComments($comments); foreach ($tags as $tag) { switch ($tag->name) { @@ -4817,7 +4817,7 @@ function parseConstLike( $link = null; $isFileCacheAllowed = true; if ($comments) { - $tags = parseDocComments($comments); + $tags = DocCommentTag::parseDocComments($comments); foreach ($tags as $tag) { if ($tag->name === 'var') { $phpDocType = $tag->getType(); @@ -4891,7 +4891,7 @@ function parseProperty( $link = null; if ($comments) { - $tags = parseDocComments($comments); + $tags = DocCommentTag::parseDocComments($comments); foreach ($tags as $tag) { if ($tag->name === 'var') { $phpDocType = $tag->getType(); @@ -4962,7 +4962,7 @@ function parseClass( $allowsDynamicProperties = false; if ($comments) { - $tags = parseDocComments($comments); + $tags = DocCommentTag::parseDocComments($comments); foreach ($tags as $tag) { if ($tag->name === 'alias') { $alias = $tag->getValue(); @@ -5067,7 +5067,7 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { $stmts = $parser->parse($code); $nodeTraverser->traverse($stmts); - $fileTags = parseDocComments(getFileDocComments($stmts)); + $fileTags = DocCommentTag::parseDocComments(getFileDocComments($stmts)); $fileInfo = new FileInfo($fileTags); $fileInfo->handleStatements($stmts, $prettyPrinter); From bb555926c4bbfb93002459c76494cd6780ae303d Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 14:14:45 -0700 Subject: [PATCH 493/503] gen_stub: deduplicate and simplify DocCommentTag processing For a lot of the structures, the parsing of doc comment tags is based on if a specific tag is present, or the value that it has if it is. Add a new helper method, `DocCommentTag::makeTagMap()`, that turns an array of tag instances into a map from tag name to value (the last value, if there are multiple uses of the same tag name). Then, for the simple cases where just a tag's presence is all that is checked, or just the (last) value is used, check the map instead of using a loop through all of the tags present. --- build/gen_stub.php | 125 +++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 72 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 64c22f1873aac..b9a8941d7c99d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4547,6 +4547,19 @@ public static function parseDocComments(array $comments): array { return $tags; } + + /** + * @param DocCommentTag[] $tags + * @return array Mapping tag names to the value (or null), + * if a tag is present multiple times the last value is used + */ + public static function makeTagMap(array $tags): array { + $map = []; + foreach ($tags as $tag) { + $map[$tag->name] = $tag->value; + } + return $map; + } } // Instances of ExposedDocComment are immutable and do not need to be cloned @@ -4629,6 +4642,13 @@ function parseFunctionLike( if ($comments) { $tags = DocCommentTag::parseDocComments($comments); + $tagMap = DocCommentTag::makeTagMap($tags); + + $isDeprecated = array_key_exists('deprecated', $tagMap); + $verify = !array_key_exists('no-verify', $tagMap); + $tentativeReturnType = array_key_exists('tentative-return-type', $tagMap); + $supportsCompileTimeEval = array_key_exists('compile-time-eval', $tagMap); + $isUndocumentable = $isUndocumentable || array_key_exists('undocumentable', $tagMap); foreach ($tags as $tag) { switch ($tag->name) { @@ -4643,18 +4663,6 @@ function parseFunctionLike( } break; - case 'deprecated': - $isDeprecated = true; - break; - - case 'no-verify': - $verify = false; - break; - - case 'tentative-return-type': - $tentativeReturnType = true; - break; - case 'return': $docReturnType = $tag->getType(); break; @@ -4667,10 +4675,6 @@ function parseFunctionLike( $refcount = $tag->getValue(); break; - case 'compile-time-eval': - $supportsCompileTimeEval = true; - break; - case 'prefer-ref': $varName = $tag->getVariableName(); if (!isset($paramMeta[$varName])) { @@ -4679,10 +4683,6 @@ function parseFunctionLike( $paramMeta[$varName][$tag->name] = true; break; - case 'undocumentable': - $isUndocumentable = true; - break; - case 'frameless-function': $framelessFunctionInfos[] = new FramelessFunctionInfo($tag->getValue()); break; @@ -4812,26 +4812,19 @@ function parseConstLike( array $attributes ): ConstInfo { $phpDocType = null; - $deprecated = false; - $cValue = null; - $link = null; - $isFileCacheAllowed = true; - if ($comments) { - $tags = DocCommentTag::parseDocComments($comments); - foreach ($tags as $tag) { - if ($tag->name === 'var') { - $phpDocType = $tag->getType(); - } elseif ($tag->name === 'deprecated') { - $deprecated = true; - } elseif ($tag->name === 'cvalue') { - $cValue = $tag->value; - } elseif ($tag->name === 'undocumentable') { - $isUndocumentable = true; - } elseif ($tag->name === 'link') { - $link = $tag->value; - } elseif ($tag->name === 'no-file-cache') { - $isFileCacheAllowed = false; - } + + $tags = DocCommentTag::parseDocComments($comments); + $tagMap = DocCommentTag::makeTagMap($tags); + + $deprecated = array_key_exists('deprecated', $tagMap); + $isUndocumentable = $isUndocumentable || array_key_exists('undocumentable', $tagMap); + $isFileCacheAllowed = !array_key_exists('no-file-cache', $tagMap); + $cValue = $tagMap['cvalue'] ?? null; + $link = $tagMap['link'] ?? null; + + foreach ($tags as $tag) { + if ($tag->name === 'var') { + $phpDocType = $tag->getType(); } } @@ -4886,22 +4879,17 @@ function parseProperty( array $attributes ): PropertyInfo { $phpDocType = null; - $isDocReadonly = false; - $isVirtual = false; - $link = null; - if ($comments) { - $tags = DocCommentTag::parseDocComments($comments); - foreach ($tags as $tag) { - if ($tag->name === 'var') { - $phpDocType = $tag->getType(); - } elseif ($tag->name === 'readonly') { - $isDocReadonly = true; - } elseif ($tag->name === 'link') { - $link = $tag->value; - } elseif ($tag->name === 'virtual') { - $isVirtual = true; - } + $tags = DocCommentTag::parseDocComments($comments); + $tagMap = DocCommentTag::makeTagMap($tags); + + $isDocReadonly = array_key_exists('readonly', $tagMap); + $link = $tagMap['link'] ?? null; + $isVirtual = array_key_exists('virtual', $tagMap); + + foreach ($tags as $tag) { + if ($tag->name === 'var') { + $phpDocType = $tag->getType(); } } @@ -4956,25 +4944,18 @@ function parseClass( ): ClassInfo { $comments = $class->getComments(); $alias = null; - $isDeprecated = false; - $isStrictProperties = false; - $isNotSerializable = false; $allowsDynamicProperties = false; - if ($comments) { - $tags = DocCommentTag::parseDocComments($comments); - foreach ($tags as $tag) { - if ($tag->name === 'alias') { - $alias = $tag->getValue(); - } else if ($tag->name === 'deprecated') { - $isDeprecated = true; - } else if ($tag->name === 'strict-properties') { - $isStrictProperties = true; - } else if ($tag->name === 'not-serializable') { - $isNotSerializable = true; - } else if ($tag->name === 'undocumentable') { - $isUndocumentable = true; - } + $tags = DocCommentTag::parseDocComments($comments); + $tagMap = DocCommentTag::makeTagMap($tags); + + $isDeprecated = array_key_exists('deprecated', $tagMap); + $isStrictProperties = array_key_exists('strict-properties', $tagMap); + $isNotSerializable = array_key_exists('not-serializable', $tagMap); + $isUndocumentable = $isUndocumentable || array_key_exists('undocumentable', $tagMap); + foreach ($tags as $tag) { + if ($tag->name === 'alias') { + $alias = $tag->getValue(); } } From c89d7a7426a2e8d90ed064880f3ba743ab56b9b9 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Thu, 8 May 2025 12:11:40 -0700 Subject: [PATCH 494/503] gen_stub: add and use `FileInfo::getLegacyVersion()` Separate out the creation of a legacy version of a FileInfo object, which has information for old versions of PHP discarded, from its subsequent use in `processStubFile()`. In the process, make `FileInfo::$legacyArginfoGeneration` private, and inline the single use of `FileInfo::getAllClassInfos()`, removing that method. --- build/gen_stub.php | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index b9a8941d7c99d..9754e6bf673f2 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -133,19 +133,7 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = } if ($fileInfo->shouldGenerateLegacyArginfo()) { - $legacyFileInfo = clone $fileInfo; - $legacyFileInfo->legacyArginfoGeneration = true; - $phpVersionIdMinimumCompatibility = $legacyFileInfo->getMinimumPhpVersionIdCompatibility(); - - foreach ($legacyFileInfo->getAllFuncInfos() as $funcInfo) { - $funcInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); - } - foreach ($legacyFileInfo->getAllClassInfos() as $classInfo) { - $classInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); - } - foreach ($legacyFileInfo->getAllConstInfos() as $constInfo) { - $constInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); - } + $legacyFileInfo = $fileInfo->getLegacyVersion(); $arginfoCode = generateArgInfoCode( basename($stubFilenameWithoutExtension), @@ -4199,7 +4187,7 @@ class FileInfo { public string $declarationPrefix = ""; public bool $generateClassEntries = false; public bool $isUndocumentable = false; - public bool $legacyArginfoGeneration = false; + private bool $legacyArginfoGeneration = false; private ?int $minimumPhpVersionIdCompatibility = null; /** @param array $fileTags */ @@ -4259,15 +4247,6 @@ public function getAllConstInfos(): array { return $result; } - /** - * @return iterable - */ - public function getAllClassInfos(): iterable { - foreach ($this->classInfos as $classInfo) { - yield $classInfo; - } - } - public function __clone() { foreach ($this->constInfos as $key => $constInfo) { @@ -4299,6 +4278,23 @@ public function shouldGenerateLegacyArginfo(): bool { return $this->minimumPhpVersionIdCompatibility !== null && $this->minimumPhpVersionIdCompatibility < PHP_80_VERSION_ID; } + public function getLegacyVersion(): FileInfo { + $legacyFileInfo = clone $this; + $legacyFileInfo->legacyArginfoGeneration = true; + $phpVersionIdMinimumCompatibility = $legacyFileInfo->getMinimumPhpVersionIdCompatibility(); + + foreach ($legacyFileInfo->getAllFuncInfos() as $funcInfo) { + $funcInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); + } + foreach ($legacyFileInfo->classInfos as $classInfo) { + $classInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); + } + foreach ($legacyFileInfo->getAllConstInfos() as $constInfo) { + $constInfo->discardInfoForOldPhpVersions($phpVersionIdMinimumCompatibility); + } + return $legacyFileInfo; + } + public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { $conds = []; foreach ($stmts as $stmt) { From 05dbf0707aa8f1cdf89f6f678e036a60ae543a60 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 18 Mar 2025 14:35:40 -0700 Subject: [PATCH 495/503] gen_stub: further reduce the number of public properties The following properties are made private: * `ArgInfo::$phpDocType` * `ClassInfo::$flags`, `::$attributes`, `::$extends`, `::$implements` * `FileInfo::$isUndocumentable` The following are made protected: * `VariableLike::$flags` --- build/gen_stub.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 9754e6bf673f2..6ec974c05a22d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -775,7 +775,7 @@ class ArgInfo { public /* readonly */ string $sendBy; public /* readonly */ bool $isVariadic; public ?Type $type; - public /* readonly */ ?Type $phpDocType; + private /* readonly */ ?Type $phpDocType; public ?string $defaultValue; /** @var AttributeInfo[] */ public array $attributes; @@ -2410,7 +2410,7 @@ public function getCExpr(): ?string abstract class VariableLike { - public int $flags; + protected int $flags; public ?Type $type; public /* readonly */ ?Type $phpDocType; private /* readonly */ ?string $link; @@ -3373,20 +3373,20 @@ public static function createFromGroups(array $attributeGroups): array { class ClassInfo { public /* readonly */ Name $name; - public int $flags; + private int $flags; public string $type; public /* readonly */ ?string $alias; private /* readonly */ ?SimpleType $enumBackingType; private /* readonly */ bool $isDeprecated; private bool $isStrictProperties; /** @var AttributeInfo[] */ - public array $attributes; + private array $attributes; private ?ExposedDocComment $exposedDocComment; private bool $isNotSerializable; /** @var Name[] */ - public /* readonly */ array $extends; + private /* readonly */ array $extends; /** @var Name[] */ - public /* readonly */ array $implements; + private /* readonly */ array $implements; /** @var ConstInfo[] */ public /* readonly */ array $constInfos; /** @var PropertyInfo[] */ @@ -4186,7 +4186,7 @@ class FileInfo { public bool $generateFunctionEntries = false; public string $declarationPrefix = ""; public bool $generateClassEntries = false; - public bool $isUndocumentable = false; + private bool $isUndocumentable = false; private bool $legacyArginfoGeneration = false; private ?int $minimumPhpVersionIdCompatibility = null; From 2b0cb760d41c1a531449b5df0733e32b1fa4c82b Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Thu, 8 May 2025 12:12:12 -0700 Subject: [PATCH 496/503] gen_stub: move `parseStubFile()` into `FileInfo` Reduce the number of global functions by moving it to static method `FileInfo::parseStubFile()`. Additionally, make `FileInfo::handleStatements()` private now that the only caller is part of the class. --- build/gen_stub.php | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 6ec974c05a22d..1d2fa79a0666c 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -95,7 +95,7 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = if (!$fileInfo = $context->parsedFiles[$stubFile] ?? null) { initPhpParser(); $stubContent = $stubCode ?? file_get_contents($stubFile); - $fileInfo = parseStubFile($stubContent); + $fileInfo = FileInfo::parseStubFile($stubContent); $context->parsedFiles[$stubFile] = $fileInfo; foreach ($fileInfo->dependencies as $dependency) { @@ -4295,7 +4295,27 @@ public function getLegacyVersion(): FileInfo { return $legacyFileInfo; } - public function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { + public static function parseStubFile(string $code): FileInfo { + $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative()); + $nodeTraverser = new PhpParser\NodeTraverser; + $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); + $prettyPrinter = new class extends Standard { + protected function pName_FullyQualified(Name\FullyQualified $node): string { + return implode('\\', $node->getParts()); + } + }; + + $stmts = $parser->parse($code); + $nodeTraverser->traverse($stmts); + + $fileTags = DocCommentTag::parseDocComments(getFileDocComments($stmts)); + $fileInfo = new FileInfo($fileTags); + + $fileInfo->handleStatements($stmts, $prettyPrinter); + return $fileInfo; + } + + private function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { $conds = []; foreach ($stmts as $stmt) { $cond = self::handlePreprocessorConditions($conds, $stmt); @@ -5031,26 +5051,6 @@ function getFileDocComments(array $stmts): array { ); } -function parseStubFile(string $code): FileInfo { - $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative()); - $nodeTraverser = new PhpParser\NodeTraverser; - $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); - $prettyPrinter = new class extends Standard { - protected function pName_FullyQualified(Name\FullyQualified $node): string { - return implode('\\', $node->getParts()); - } - }; - - $stmts = $parser->parse($code); - $nodeTraverser->traverse($stmts); - - $fileTags = DocCommentTag::parseDocComments(getFileDocComments($stmts)); - $fileInfo = new FileInfo($fileTags); - - $fileInfo->handleStatements($stmts, $prettyPrinter); - return $fileInfo; -} - /** * @template T * @param iterable $infos From 84f82d0a1c755a707811d3d195335810cc5f33b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 9 May 2025 13:33:09 +0200 Subject: [PATCH 497/503] gen_stub: Fix `ce_flags` generation for compatibility mode (#18507) * gen_stub: Fix `ce_flags` generation for compatibility mode Fixes php/php-src#18506 * gen_stub: Improve output for ce_flags compatibility --- build/gen_stub.php | 24 +++++++++++------------- ext/zend_test/test.c | 3 +++ ext/zend_test/test.stub.php | 7 +++++++ ext/zend_test/test_arginfo.h | 21 ++++++++++++++++++++- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 45641f4061b9c..f1d8b43862e62 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -3282,18 +3282,13 @@ public function getRegistration(array $allConstInfos): string $code .= "{\n"; - $flagCodes = generateVersionDependentFlagCode("%s", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); - $flags = implode("", $flagCodes); - $classMethods = ($this->funcInfos === []) ? 'NULL' : "class_{$escapedName}_methods"; if ($this->type === "enum") { $name = addslashes((string) $this->name); $backingType = $this->enumBackingType ? $this->enumBackingType->toTypeCode() : "IS_UNDEF"; $code .= "\tzend_class_entry *class_entry = zend_register_internal_enum(\"$name\", $backingType, $classMethods);\n"; - if ($flags !== "") { - $code .= "\tclass_entry->ce_flags |= $flags\n"; - } + $code .= implode("", generateVersionDependentFlagCode("\tclass_entry->ce_flags = %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility)); } else { $code .= "\tzend_class_entry ce, *class_entry;\n\n"; if (count($this->name->getParts()) > 1) { @@ -3310,22 +3305,25 @@ public function getRegistration(array $allConstInfos): string $code .= "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n"; } - $code .= "\tclass_entry = zend_register_internal_class_with_flags(&ce, " . (isset($this->extends[0]) ? "class_entry_" . str_replace("\\", "_", $this->extends[0]->toString()) : "NULL") . ", " . ($flags ?: 0) . ");\n"; + $template = "\tclass_entry = zend_register_internal_class_with_flags(&ce, " . (isset($this->extends[0]) ? "class_entry_" . str_replace("\\", "_", $this->extends[0]->toString()) : "NULL") . ", %s);\n"; + $entries = generateVersionDependentFlagCode($template, $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ? max($this->phpVersionIdMinimumCompatibility, PHP_84_VERSION_ID) : null); + if ($entries !== []) { + $code .= implode("", $entries); + } else { + $code .= sprintf($template, "0"); + } if (!$php84MinimumCompatibility) { $code .= "#else\n"; $code .= "\tclass_entry = zend_register_internal_class_ex(&ce, " . (isset($this->extends[0]) ? "class_entry_" . str_replace("\\", "_", $this->extends[0]->toString()) : "NULL") . ");\n"; - if ($flags !== "") { - $code .= "\tclass_entry->ce_flags |= $flags;\n"; - } + $code .= implode("", generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility)); $code .= "#endif\n"; } } else { $code .= "\tclass_entry = zend_register_internal_interface(&ce);\n"; - if ($flags !== "") { - $code .= "\tclass_entry->ce_flags |= $flags\n"; - } + $code .= implode("", generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility)); + } } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index dbad83fb0e843..d52b8aa0cd172 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -54,6 +54,7 @@ ZEND_DECLARE_MODULE_GLOBALS(zend_test) static zend_class_entry *zend_test_interface; static zend_class_entry *zend_test_class; static zend_class_entry *zend_test_child_class; +static zend_class_entry *zend_test_gen_stub_flag_compatibility_test; static zend_class_entry *zend_attribute_test_class; static zend_class_entry *zend_test_trait; static zend_class_entry *zend_test_attribute; @@ -1271,6 +1272,8 @@ PHP_MINIT_FUNCTION(zend_test) memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_test_class_handlers.get_method = zend_test_class_method_get; + zend_test_gen_stub_flag_compatibility_test = register_class_ZendTestGenStubFlagCompatibilityTest(); + zend_attribute_test_class = register_class_ZendAttributeTest(); zend_test_trait = register_class__ZendTestTrait(); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index fbfd93da40975..213c1b3f57476 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -85,6 +85,13 @@ class _ZendTestChildClass extends _ZendTestClass public function returnsThrowable(): Exception {} } + /** + * @not-serializable + */ + final class ZendTestGenStubFlagCompatibilityTest { + + } + class ZendAttributeTest { /** @var int */ #[ZendTestRepeatableAttribute] diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index eb83d34fa1f59..9888ba39c14e4 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a7b5de3e4868f9a4aef78da6b98bbce882e129a9 */ + * Stub hash: 20a58913caf419fb60a3bc9cf275db605e2c3b0f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -774,6 +774,25 @@ static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *cl return class_entry; } +static zend_class_entry *register_class_ZendTestGenStubFlagCompatibilityTest(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "ZendTestGenStubFlagCompatibilityTest", NULL); +#if (PHP_VERSION_ID >= 80400) + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NOT_SERIALIZABLE); +#else + class_entry = zend_register_internal_class_ex(&ce, NULL); +#if (PHP_VERSION_ID >= 80100) + class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NOT_SERIALIZABLE; +#elif (PHP_VERSION_ID >= 80000) + class_entry->ce_flags |= ZEND_ACC_FINAL; +#endif +#endif + + return class_entry; +} + static zend_class_entry *register_class_ZendAttributeTest(void) { zend_class_entry ce, *class_entry; From e11a702c0569a2b5a2282fcba4862731ebfb91a3 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Fri, 9 May 2025 14:08:58 +0200 Subject: [PATCH 498/503] ext/hash: tests for md5 and sha1 compatibility (#18525) Add test cases to check compatibility between the `hash("algo")` and `md5()`/`sha1()` functions. --- ext/hash/tests/md5.phpt | 2 ++ ext/hash/tests/sha1.phpt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ext/hash/tests/md5.phpt b/ext/hash/tests/md5.phpt index b03efadd132e3..2a51146f9777e 100644 --- a/ext/hash/tests/md5.phpt +++ b/ext/hash/tests/md5.phpt @@ -6,9 +6,11 @@ echo hash('md5', '') . "\n"; echo hash('md5', 'a') . "\n"; echo hash('md5', '012345678901234567890123456789012345678901234567890123456789') . "\n"; echo hash('md5', str_repeat('a', 1000000)) . "\n"; +var_dump(hash('md5', 'string') === md5('string')); ?> --EXPECT-- d41d8cd98f00b204e9800998ecf8427e 0cc175b9c0f1b6a831c399e269772661 1ced811af47ead374872fcca9d73dd71 7707d6ae4e027c70eea2a935c2296f21 +bool(true) diff --git a/ext/hash/tests/sha1.phpt b/ext/hash/tests/sha1.phpt index ef7ed6e64ce73..cd22f35ea4015 100644 --- a/ext/hash/tests/sha1.phpt +++ b/ext/hash/tests/sha1.phpt @@ -10,6 +10,7 @@ echo hash('sha1', '012345678901234567890123456789012345678901234567890123456789' echo hash('sha1', 'abc') . "\n"; echo hash('sha1', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq') . "\n"; echo hash('sha1', str_repeat('a', 1000000)) . "\n"; +var_dump(hash('sha1', 'string') === sha1('string')) . "\n"; ?> --EXPECT-- da39a3ee5e6b4b0d3255bfef95601890afd80709 @@ -18,3 +19,4 @@ f52e3c2732de7bea28f216d877d78dae1aa1ac6a a9993e364706816aba3e25717850c26c9cd0d89d 84983e441c3bd26ebaae4aa1f95129e5e54670f1 34aa973cd4c4daa4f61eeb2bdbad27316534016f +bool(true) From 331ac35f5802145648fefa6312aa54c7306b93d6 Mon Sep 17 00:00:00 2001 From: Richard Schneeman Date: Sun, 11 May 2025 08:53:56 -0500 Subject: [PATCH 499/503] Fix visibility of whitespace in config output (#18527) When a config var has whitespace (especially trailing whitespace) it is hard to see. This commit wraps the values (if they exist) in double quotes, so the difference is visually observable: Before: ``` $ export PHP_INI_SCAN_DIR="/opt/homebrew/etc/php/8.4/conf.d " $ ./sapi/cli/php --ini Configuration File (php.ini) Path: /usr/local/lib Loaded Configuration File: /opt/homebrew/etc/php/8.4/conf.d Scan for additional .ini files in: (none) Additional .ini files parsed: (none) ``` > Note > The above output has trailing whitespace that is not visible, you can see it if you copy it into an editor: After: ``` $ ./sapi/cli/php --ini Configuration File (php.ini) Path: "/usr/local/lib" Loaded Configuration File: "/opt/homebrew/etc/php/8.4/conf.d " Scan for additional .ini files in: (none) Additional .ini files parsed: (none) ``` Above the whitespace is now visible `/opt/homebrew/etc/php/8.4/conf.d `. Close #18390 --- sapi/cli/php_cli.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 91dd0864c2fbb..8a8f13895340f 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -1106,9 +1106,17 @@ static int do_cli(int argc, char **argv) /* {{{ */ case PHP_CLI_MODE_SHOW_INI_CONFIG: { - zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH); - zend_printf("Loaded Configuration File: %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)"); - zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)"); + zend_printf("Configuration File (php.ini) Path: \"%s\"\n", PHP_CONFIG_FILE_PATH); + if (php_ini_scanned_path) { + zend_printf("Loaded Configuration File: \"%s\"\n", php_ini_scanned_path); + } else { + zend_printf("Loaded Configuration File: (none)\n"); + } + if (php_ini_opened_path) { + zend_printf("Scan for additional .ini files in: \"%s\"\n", php_ini_opened_path); + } else { + zend_printf("Scan for additional .ini files in: (none)\n"); + } zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)"); break; } From 8d2682fc50a8fd72ca5ebcd4b91e1cb5794bb394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 12 May 2025 08:44:46 +0200 Subject: [PATCH 500/503] standard: Take `zend.assertions` into account for dynamic calls to `assert()` (#18521) Fixes php/php-src#18509. --- NEWS | 2 ++ ext/standard/assert.c | 6 +++++- ext/standard/tests/assert/gh18509.phpt | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/assert/gh18509.phpt diff --git a/NEWS b/NEWS index 15b8fa714223b..f5dd8fe320839 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ PHP NEWS - Standard: . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos) + . Fixed bug GH-18509 (Dynamic calls to assert() ignore zend.assertions). + (timwolla) - Windows: . Fix leak+crash with sapi_windows_set_ctrl_handler(). (nielsdos) diff --git a/ext/standard/assert.c b/ext/standard/assert.c index f0b6adadbe17d..258447576e1f4 100644 --- a/ext/standard/assert.c +++ b/ext/standard/assert.c @@ -178,7 +178,11 @@ PHP_FUNCTION(assert) zend_string *description_str = NULL; zend_object *description_obj = NULL; - if (!ASSERTG(active)) { + /* EG(assertions) <= 0 is only reachable by dynamic calls to assert(), + * since calls known at compile time will skip the entire call when + * assertions are disabled. + */ + if (!ASSERTG(active) || EG(assertions) <= 0) { RETURN_TRUE; } diff --git a/ext/standard/tests/assert/gh18509.phpt b/ext/standard/tests/assert/gh18509.phpt new file mode 100644 index 0000000000000..2bf1a04c87c69 --- /dev/null +++ b/ext/standard/tests/assert/gh18509.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-18509: Dynamic calls to assert() ignore zend.assertions +--INI-- +zend.assertions=0 +--FILE-- + +--EXPECT-- +array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + bool(true) +} From 5e65d8e126ba2674f9e0713cf305f40c5a8a7805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 12 May 2025 10:53:51 +0200 Subject: [PATCH 501/503] standard: Remove `php_std_date()` C API (#18522) This function is unused and trivially replaced by `php_format_date()` (which is already used to format date headers in the CLI server and ext/session). Remove it to slim down the codebase, allowing to remove an entire header (and a source file once the deprecated `strptime()` userland function is removed). --- UPGRADING.INTERNALS | 2 ++ ext/standard/datetime.c | 38 ------------------------------------- ext/standard/datetime.h | 23 ---------------------- ext/standard/php_standard.h | 1 - 4 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 ext/standard/datetime.h diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 7c7f093e50cce..2ed9c2510521c 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -64,6 +64,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES - ext/standard . Added php_url_decode_ex() and php_raw_url_decode_ex() that unlike their non-ex counterparts do not work in-place. + . The php_std_date() function has been removed. Use php_format_date() with + the "D, d M Y H:i:s \\G\\M\\T" format instead. ======================== 4. OpCode changes diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c index 24569f8f6a390..93f47f0f858bc 100644 --- a/ext/standard/datetime.c +++ b/ext/standard/datetime.c @@ -17,50 +17,12 @@ */ #include "php.h" -#include "zend_operators.h" -#include "datetime.h" #include "php_globals.h" #include #ifdef HAVE_SYS_TIME_H # include #endif -#include - -static const char * const mon_short_names[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static const char * const day_short_names[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -/* {{{ PHPAPI char *php_std_date(time_t t) - Return date string in standard format for http headers */ -PHPAPI char *php_std_date(time_t t) -{ - struct tm *tm1, tmbuf; - char *str; - - tm1 = php_gmtime_r(&t, &tmbuf); - str = emalloc(81); - str[0] = '\0'; - - if (!tm1) { - return str; - } - - snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT", - day_short_names[tm1->tm_wday], - tm1->tm_mday, - mon_short_names[tm1->tm_mon], - tm1->tm_year + 1900, - tm1->tm_hour, tm1->tm_min, tm1->tm_sec); - - str[79] = 0; - return (str); -} -/* }}} */ #ifdef HAVE_STRPTIME #ifndef HAVE_DECL_STRPTIME diff --git a/ext/standard/datetime.h b/ext/standard/datetime.h deleted file mode 100644 index da87cb8ece493..0000000000000 --- a/ext/standard/datetime.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | https://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andi Gutmans | - | Zeev Suraski | - +----------------------------------------------------------------------+ -*/ - -#ifndef DATETIME_H -#define DATETIME_H - -PHPAPI char *php_std_date(time_t t); - -#endif /* DATETIME_H */ diff --git a/ext/standard/php_standard.h b/ext/standard/php_standard.h index 5bf41431eeabb..78eba25f11a58 100644 --- a/ext/standard/php_standard.h +++ b/ext/standard/php_standard.h @@ -30,7 +30,6 @@ #include "php_filestat.h" #include "php_browscap.h" #include "pack.h" -#include "datetime.h" #include "url.h" #include "pageinfo.h" #include "fsock.h" From ba4567a987aac3f349f548785854b5a62ffeb6ec Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 12 May 2025 18:45:01 +0200 Subject: [PATCH 502/503] Fix OSS-Fuzz #416302790 (#18537) The parser accepted invalid code: consts are only valid at the top level, but because GH-16952 changed the grammar it was incorrectly allowed at all places that allowed attributed statements. Fix this by introducing a variant of attributed_statement for the top level. --- Zend/tests/constants/oss_fuzz_416302790.phpt | 10 ++++++++++ Zend/zend_language_parser.y | 10 +++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/constants/oss_fuzz_416302790.phpt diff --git a/Zend/tests/constants/oss_fuzz_416302790.phpt b/Zend/tests/constants/oss_fuzz_416302790.phpt new file mode 100644 index 0000000000000..7ace0a72867da --- /dev/null +++ b/Zend/tests/constants/oss_fuzz_416302790.phpt @@ -0,0 +1,10 @@ +--TEST-- +OSS-Fuzz #416302790 +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected token "const" in %s on line %d diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 0c5bb36501e72..08b2ac6b3f39b 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -279,7 +279,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type isset_variable type return_type type_expr type_without_static %type identifier type_expr_without_static union_type_without_static_element union_type_without_static intersection_type_without_static %type inline_function union_type_element union_type intersection_type -%type attributed_statement attributed_class_statement attributed_parameter +%type attributed_statement attributed_top_statement attributed_class_statement attributed_parameter %type attribute_decl attribute attributes attribute_group namespace_declaration_name %type match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list %type enum_declaration_statement enum_backing_type enum_case enum_case_expr @@ -391,13 +391,17 @@ attributed_statement: | trait_declaration_statement { $$ = $1; } | interface_declaration_statement { $$ = $1; } | enum_declaration_statement { $$ = $1; } +; + +attributed_top_statement: + attributed_statement { $$ = $1; } | T_CONST const_list ';' { $$ = $2; } ; top_statement: statement { $$ = $1; } - | attributed_statement { $$ = $1; } - | attributes attributed_statement { $$ = zend_ast_with_attributes($2, $1); } + | attributed_top_statement { $$ = $1; } + | attributes attributed_top_statement { $$ = zend_ast_with_attributes($2, $1); } | T_HALT_COMPILER '(' ')' ';' { $$ = zend_ast_create(ZEND_AST_HALT_COMPILER, zend_ast_create_zval_from_long(zend_get_scanned_file_offset())); From 4122daa49421b0d079857d669b041e0f23f328ff Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 12 May 2025 19:03:59 +0100 Subject: [PATCH 503/503] ext/date: various array optimisations. (#18382) --- ext/date/php_date.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index a991c5072f941..6f12a26e465e8 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1408,7 +1408,7 @@ PHP_FUNCTION(localtime) ts->zone_type = TIMELIB_ZONETYPE_ID; timelib_unixtime2local(ts, (timelib_sll) timestamp); - array_init(return_value); + array_init_size(return_value, 9); if (associative) { add_assoc_long(return_value, "tm_sec", ts->s); @@ -1421,6 +1421,7 @@ PHP_FUNCTION(localtime) add_assoc_long(return_value, "tm_yday", timelib_day_of_year(ts->y, ts->m, ts->d)); add_assoc_long(return_value, "tm_isdst", ts->dst); } else { + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); add_next_index_long(return_value, ts->s); add_next_index_long(return_value, ts->i); add_next_index_long(return_value, ts->h); @@ -1462,7 +1463,7 @@ PHP_FUNCTION(getdate) ts->zone_type = TIMELIB_ZONETYPE_ID; timelib_unixtime2local(ts, (timelib_sll) timestamp); - array_init(return_value); + array_init_size(return_value, 11); add_assoc_long(return_value, "seconds", ts->s); add_assoc_long(return_value, "minutes", ts->i); @@ -3059,14 +3060,14 @@ static void zval_from_error_container(zval *z, const timelib_error_container *er zval element; add_assoc_long(z, "warning_count", error->warning_count); - array_init(&element); + array_init_size(&element, error->warning_count); for (i = 0; i < error->warning_count; i++) { add_index_string(&element, error->warning_messages[i].position, error->warning_messages[i].message); } add_assoc_zval(z, "warnings", &element); add_assoc_long(z, "error_count", error->error_count); - array_init(&element); + array_init_size(&element, error->error_count); for (i = 0; i < error->error_count; i++) { add_index_string(&element, error->error_messages[i].position, error->error_messages[i].message); } @@ -4275,7 +4276,7 @@ PHP_FUNCTION(timezone_transitions_get) } #define add_nominal() \ - array_init(&element); \ + array_init_size(&element, 5); \ add_assoc_long(&element, "ts", timestamp_begin); \ add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, timestamp_begin, 0)); \ add_assoc_long(&element, "offset", tzobj->tzi.tz->type[0].offset); \ @@ -4284,7 +4285,7 @@ PHP_FUNCTION(timezone_transitions_get) add_next_index_zval(return_value, &element); #define add(i,ts) \ - array_init(&element); \ + array_init_size(&element, 5); \ add_assoc_long(&element, "ts", ts); \ add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \ add_assoc_long(&element, "offset", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].offset); \ @@ -4293,7 +4294,7 @@ PHP_FUNCTION(timezone_transitions_get) add_next_index_zval(return_value, &element); #define add_by_index(i,ts) \ - array_init(&element); \ + array_init_size(&element, 5); \ add_assoc_long(&element, "ts", ts); \ add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \ add_assoc_long(&element, "offset", tzobj->tzi.tz->type[i].offset); \ @@ -4302,7 +4303,7 @@ PHP_FUNCTION(timezone_transitions_get) add_next_index_zval(return_value, &element); #define add_from_tto(to,ts) \ - array_init(&element); \ + array_init_size(&element, 5); \ add_assoc_long(&element, "ts", ts); \ add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \ add_assoc_long(&element, "offset", (to)->offset); \ @@ -5336,6 +5337,7 @@ PHP_FUNCTION(timezone_identifiers_list) table = timelib_timezone_identifiers_list((timelib_tzdb*) tzdb, &item_count); array_init(return_value); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); for (i = 0; i < item_count; ++i) { if (what == PHP_DATE_TIMEZONE_PER_COUNTRY) {